ORM对应的关系
类------------->表
类属性------->表字段
类对象------->表记录
1、ORM简介
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。那么,到底如何实现持久化呢?一种简单的方案是采用硬编码方式,为每一种可能的数据库访问操作提供单独的方法。
这种方案存在以下不足:
1.持久化层缺乏弹性。一旦出现业务需求的变更,就必须修改持久化层的接口
2.持久化层同时与域模型与关系数据库模型绑定,不管域模型还是关系数据库模型发生变化,毒药修改持久化曾的相关程序代码,增加了软件的维护难度。
ORM提供了实现持久化层的另一种模式,它采用映射元数据来描述对象关系的映射,使得ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。Java典型的ORM中间件有:Hibernate,ibatis,speedframework。
ORM的方法论基于三个核心原则:
· 简单:以最基本的形式建模数据。
· 传达性:数据库结构被任何人都能理解的语言文档化。
· 精确性:基于数据模型创建正确标准化了的结构。
2、ORM的概念
让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。
ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
3、ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
4、ORM的优缺点
ORM的缺点是会牺牲程序的执行效率和会固定思维模式。
从系统结构上来看,采用ORM的系统一般都是多层系统,系统的层次多了,效率就会降低。ORM是一种完全的面向对象的做法,而面向对象的做法也会对性能产生一定的影响。
在我们开发系统时,一般都有性能问题。性能问题主要产生在算法不正确和与数据库不正确的使用上。ORM所生成的代码一般不太可能写出很高效的算法,在数据库应用上更有可能会被误用,主要体现在对持久对象的提取和和数据的加工处理上,如果用上了ORM,程序员很有可能将全部的数据提取到内存对象中,然后再进行过滤和加工处理,这样就容易产生性能问题。
在对对象做持久化时,ORM一般会持久化所有的属性,有时,这是不希望的。
但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。但我们不能指望工具能一劳永逸的解决所有问题,有些问题还是需要特殊处理的,但需要特殊处理的部分对绝大多数的系统,应该是很少的。
5、ORM实践
(1)创建数据库bms
(2)创建文件迁移
遇到问题:
D:\biancheng\pythonCODE\myorm>python
'python' 不是内部或外部命令,也不是可运行的程序或批处理文件。
问题解决:
D:\biancheng\pythonCODE\myorm>activate base
(base) D:\biancheng\pythonCODE\myorm>python
Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
运到问题:
(base) D:\biancheng\pythonCODE\myorm>python manage.py makemigrations
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\core\management\__init__.py", line 357, in execute
django.setup()
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\apps\registry.py", line 114, in populate
app_config.import_models()
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\apps\config.py", line 211, in import_models
self.models_module = import_module(models_module_name)
File "D:\Aconda\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\contrib\auth\models.py", line 2, in <module>
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\contrib\auth\base_user.py", line 47, in <module>
class AbstractBaseUser(models.Model):
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\models\base.py", line 117, in __new__
new_class.add_to_class('_meta', Options(meta, app_label))
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\models\base.py", line 321, in add_to_class
value.contribute_to_class(cls, name)
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\models\options.py", line 204, in contribute_to_class
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\__init__.py", line 28, in __getattr__
return getattr(connections[DEFAULT_DB_ALIAS], item)
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\utils.py", line 201, in __getitem__
backend = load_backend(db['ENGINE'])
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\utils.py", line 110, in load_backend
return import_module('%s.base' % backend_name)
File "D:\Aconda\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "D:\Aconda\lib\site-packages\django-2.2.4-py3.6.egg\django\db\backends\mysql\base.py", line 36, in <module>
raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.
问题解决:对mysqlclient进行升级,因为版本太低:pip3 install mysqlclient
但是呢,在进行完以上操作仍然出现问题,所以接着解决:
找到路径下的文件,将文件base.py的下面代码进行注释:
此时继续出现新问题:
此时找到此路径下的文件:
将operations.py文件中的代码进行注释:
(3)数据库创建表
以上问题解决后,在cmd中输入:python manage.py makemigrations
成功进行文件迁移,得到新文件:
0001_initial.py
# Generated by Django 2.2.4 on 2019-08-22 11:29
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Book',
fields=[
('nid', models.AutoField(primary_key=True, serialize=False)),
('title', models.CharField(max_length=32)),
('price', models.DecimalField(decimal_places=2, max_digits=8)),
('pub_date', models.DateTimeField()),
('publish', models.CharField(max_length=32)),
],
),
]
接着在cmd程序输入python manage.py migrate
此时看到数据库中多了一张表bms
接着创建一个新的app项目,在cmd中输入python manage.py startapp app04,有:
此时再cmd输入代码测试:
继续输入:
继续输入创建app03表:
此时:
数据库迁移,其实就是在项目manage.pyl路径下执行如下命令即可
python manage.py makemigrations
python manage.py migrate
查看表的结构:
在app03的views中输入:
def addbook(request):
"""
添加表记录
:param request:
:return:
"""
#实例化一张表
book = Book(title="三国演义",price=123,pub_date="2019-09-09",publish="清华大学出版社")
#保存数据表
book.save()
return HttpResponse("OK")
如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
All Code:项目代码
本期学习到此结束,你的关注是我持续更新动力。