摘要
本文部分内容来源于网络,个人收集整理,请勿传播
ORM英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。
ORM的优点
- 隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
- ORM使我们构造固化数据结构变得简单易行。
缺点
无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。
sqlalchemy
在Python中,最有名的ORM框架是SQLAlchemy。
SQLAlchemy是一个基于Python实现的ORM框架。该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
1 | #由于mysqldb依然不支持py3,所以这里我们用pymysql与sqlalchemy交互 |
组成部分
- Engine,框架的引擎
- Connection Pooling ,数据库连接池
- Dialect,选择连接数据库的DB API种类
- 用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作
- Schema/Types,架构和类型
- SQL Exprression Language,SQL表达式语言
SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:
1 | MySQL-Python |
sqlalchemy基本使用
执行原生sql(不常用)
1 | import time |
创建表
1 | #!/usr/bin/env python |
多个表
指定关联列:hobby = relationship(“Hobby”, backref=’pers’,foreign_keys=”Person.hobby_id”)
1 | #!/usr/bin/env python |
另一种创建方式(不常用)
1 | from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey |
操作数据库表
1 | from sqlalchemy.orm import sessionmaker |
基于scoped_session实现线程安全
1 | from sqlalchemy.orm import sessionmaker |
多线程执行示例
1 | #!/usr/bin/env python |
基于relationship操作ForeignKey
1 | import time |
基于relationship操作m2m
1 | import time |
其他
1 | import time |
常用操作
1 | import time |
增加数据
1 | # 添加一条数据 |
删除数据
1 | session.query(Users).filter(Users.id > 2).delete() |
修改
1 | # update修改 |
查询
1 | my_user = Session.query(User).filter_by(name="alex").first() |
此时你看到的输出是这样的应该
1 | <__main__.User object at 0x105b4ba90> |
不过刚才上面的显示的内存对象对址你是没办法分清返回的是什么数据的,除非打印具体字段看一下,如果想让它变的可读,只需在定义表的类下面加上这样的代码
1 | def __repr__(self): |
查询操作
1 | # 获取所有数据 |
其他常用操作
1 | # 条件 |
回滚
1 | my_user = Session.query(User).filter_by(id=1).first() |
事务操作
1 | # 事务操作 |
外键关联
我们创建一个addresses表,跟user表关联
1 | from sqlalchemy import ForeignKey |
表创建好后,我们可以这样反查试试
1 | obj = Session.query(User).first() |
1 | obj = Session.query(User).filter(User.name=='rain').all()[0] |
多外键关联
下表中,Customer表有2个字段都关联了Address表
1 | from sqlalchemy import Integer, ForeignKey, String, Column |
创建表结构是没有问题的,但你Address表中插入数据时会报下面的错
1 | sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join |
解决办法如下
1 | class Customer(Base): |
这样sqlachemy就能分清哪个外键是对应哪个字段了
多对多关系
现在来设计一个能描述“图书”与“作者”的关系的表结构,需求是
- 一本书可以有好几个作者一起出版
- 一个作者可以写好几本书
1 | #一本书可以有多个作者,一个作者又可以出版多本书 |
接下来创建几本书和作者
1 | Session_class = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例 |
此时,手动连上mysql,分别查看这3张表,你会发现,book_m2m_author中自动创建了多条纪录用来连接book和author表
1 | mysql> select * from books; |
此时,我们去用orm查一下数据
1 | print('--------通过书表查关联的作者---------') |
多对多删除
删除数据时不用管boo_m2m_authors , sqlalchemy会自动帮你把对应的数据删除
通过书删除作者
1 | author_obj =s.query(Author).filter_by(name="Jack").first() |
直接删除作者
删除作者时,会把这个作者跟所有书的关联关系数据也自动删除
1 | author_obj =s.query(Author).filter_by(name="Alex").first() |