Python与数据库[2] -> 关系对象映射/ORM[0] -> ORM 与 sqlalchemy 模块

时间:2023-01-20 22:24:29

ORM 与 sqlalchemy


1 关于ORM / About ORM

1.1 ORM定义 / Definition of ORM

ORM(Object Relational Mapping),即对象关系映射。简单的说,ORM将数据库中的与面向对象语言中的建立了一种对应关系。这样,我们要操作数据库,数据库中的表或者表中的一条记录就可以直接通过操作类或者类实例来完成。Python与数据库[2] -> 关系对象映射/ORM[0] -> ORM 与 sqlalchemy 模块

如果写程序用适配器(Adaptor)和程序交互,则需要要写原生SQL语句。如果进行复杂的查询,那SQL语句就要进行一点一点拼接,而且不太有重用性,扩展不方便。而且写的SQL语句可能不高效,导致程序运行也变慢。ORM 相当于把数据库实例化了,在代码操作SQL数据库中又加了ORM这一层。

ORM的优点:

  1. 隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
  2. ORM使我们构造固化数据结构变得简单易行。

ORM的缺点:

无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。

1.2 Active Record模式 / Active Record Mode

       Active Record模式属于软件设计模式的一种,它将对象的操作与数据库的动作对应起来,ORM对象本质是表中的数据行,也就是当操作ORM对象的属性时,会自动对数据库进行相应的操作。

       目前sqlalchemy已将其自带的声明层修改为Active Record模式。

2 sqlalchemy / sqlalchemy library

SQLAlchemy 是Python 社区最知名的 ORM 工具之一,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型。使用方式可以参考官方文档

2.1 关于sqlalchemy / About sqlalchemy

2.1.1 版本区别 / Difference between Version

       对于sqlalchemy来说,存在一个值得注意的问题,当sqlalchemy的版本大于1.0,且使用pyodbc适配器的时候,会对ODBC所使用的驱动参数要求进行指明。而在旧版本例如0.9.9中则无需指明会进行自动选择。

例如连接SQL Server,在0.9.9版本中,可以不指定驱动,

connection = 'mssql+pyodbc://username:password@host:port/database'  

而在1.0以上的版本中则需要对驱动进行指定,

connection = 'mssql+pyodbc://username:password@host:port/database?Driver=SQL Server'  

2.1.2 使用参考 / Usage Reference

使用的方式除了参考官方文档外,还有以下链接:

http://blog.csdn.net/fgf00/article/details/52949973

http://www.cnblogs.com/liu-yao/p/5342656.html

 

2.2 模块 / Module

sqlalchemy有许多模块,在sqlalchemy包的__init__中可以看到,初始化时对各个模块中比较常用的模块进行了导入,下面将分别对这些模块中较为重要的函数或类进行一定介绍,若无说明则以.module_name代指sqlalchemy.module_name。

由于sqlalchemy中的导入关系,具体实现方法所在位置参考源代码

2.2.1 .engine模块

在.engine的__init__中,包含了对该模块内的各个py文件介绍,engine模块中的介绍如下,engine模块定义了一套使用高级结构语句,连接管理,执行及结果的组件,用于实现与DB-API模块接口。其中最主要的类在于Engine,主要构建函数为create_engine()。

2.2.1.1 create_engine()函数

函数调用: engine = create_engine(url, **kwargs)

函数功能:创建驱动实例

传入参数: url, kwargs

url: str类型,dialect[+driver]://user:password@host/dbname[?key=value..]形式存在

echo: bool类型,可以设置执行时是否显示原始SQL语句

返回参数: engine

engine: obj类型,返回的一个引擎实例

Note: ‘dialect’ is a database name such as ‘mysql’, ‘oracle’, ‘postgresql’, etc., ‘driver’ is the name of a DBAPI, such as ‘psycopg2’, ‘pyodbc’, ‘cx_oracle’, etc. Alternatively, the URL can be an instance of :class: ‘~sqlalchemy.engine.url.URL’.

2.2.2 .orm模块

2.2.2.1 relationship()函数

函数调用: t_rel = orm.relationship(argument, secondary=None, backref=None, **kargs)

函数功能:生成一个关系属性(relationship property)对象实例

传入参数: argument, secondary, backref,

argument: str类型,一个映射的类,或者实际的类,映射器实例,代表关系对象的目标

secondary: obj类型,在多对多的关系对象中,用于指明中间表,通常这是一个关系表的类实例

backref: str类型,用于指明当前关系属性需要放置映射器类的名称

返回参数:

t_rel: obj类型,关系对象实例

E.g.:

1 from sqlalchemy.ext.declarative import declarative_base  
2   
3 Base = declarative_base()  
4   
5 class Parent(Base):  
6     __tablename__ = 'parent'  
7     id = Column(Integer, primary_key=True)  
8     children = relationship("Child", order_by="Child.id")  

 

2.2.2.2 Session模块

2.2.2.2.1 sessionmaker

类实例化: Session = orm.sessionmaker(bind=None, **kwargs)

类的功能:可配置的Session工厂函数,会创建一个新的Session类

传入参数: bind, kwargs

bind: obj类型,可传入一个连接对象(引擎),bind=engine

返回参数: Session

Session: class类型,返回的一个Session类,可以用于产生session实例

Note: 重新传入的参数会覆盖原本传入的参数

E.g.:

1 # global scope  
2 Session = sessionmaker(autoflush=False)  
3 # later, in a local scope, create and use a session:  
4 sess = Session()  
5 # Any keyword arguments sent to the constructor itself will override the  
6 # "configured" keywords::  
7 Session = sessionmaker()  
8 # bind an individual session to a connection  
9 sess = Session(bind=connection)  

 

2.2.2.2.2 Session

类实例化: ses = Session()

类的功能:生成一个会话实例

传入参数: kwargs

返回参数: ses

ses: obj类型,返回的一个Session类实例

Note: 此处的参数可由sessionmaker传入,也可在实例化使自主重定义

2.2.2.2.2.1 execute()方法

函数调用: re = ses.execute(clause, params=None, mapper=None, bind=None)

函数功能:利用会话对象执行SQL语句或一个表达式结构

传入参数: clause, params, mapper, bind

clause: str/obj类型,可以传入原生SQL语句字符串(与适配器相同),或者条件表达式

params: dict/list of dict类型,传入单个字典时,使用适配器execute,多个executemany,参考适配器部分内容

返回参数: re

re: obj类型,返回的结果,ResultProxy结果代理类,可从中获取信息

E.g.:

result = session.execute(  
                        user_table.select().where(user_table.c.id == 5)  
                    )  
  
        :meth:`~.Session.execute` accepts any executable clause construct,  
        such as :func:`~.sql.expression.select`,  
        :func:`~.sql.expression.insert`,  
        :func:`~.sql.expression.update`,  
        :func:`~.sql.expression.delete`, and  
        :func:`~.sql.expression.text`.  Plain SQL strings can be passed  
        as well, which in the case of :meth:`.Session.execute` only  
        will be interpreted the same as if it were passed via a  
        :func:`~.expression.text` construct.  That is, the following usage::  
  
            result = session.execute(  
                        "SELECT * FROM user WHERE id=:param",  
                        {"param":5}  
                    )  
  
        is equivalent to::  
  
            from sqlalchemy import text  
            result = session.execute(  
                        text("SELECT * FROM user WHERE id=:param"),  
                        {"param":5}  
                    ) 

 

2.2.2.2.2.2 commit()方法

函数调用: ses.commit()

函数功能:提交会话事务(Flush pending changes and commit the current transaction),当没有待提交的事务时,会引起一个InvalidRequestError

传入参数:

返回参数:

2.2.2.2.2.3 close()方法

函数调用: ses.close()

函数功能:关闭会话

传入参数:

返回参数:

2.2.2.2.2.4 add()方法

函数调用: ses.add(instance)

函数功能:利用会话对象对表格添加数据

传入参数: instance

instance: obj类型,需要添加的表格信息对象

返回参数:

       E.g.: 

session.add(Table_name(id=6, name='Momo')) 

2.2.2.2.2.5 add_all()方法

函数调用: ses.add_all(instances)

函数功能:利用会话对象对表格添加多项数据

传入参数: instances

instances: iterable类型,需要添加的表格信息可迭代对象

返回参数:

Note: 实际实现为for循环instances后利用add函数进行添加

2.2.2.2.2.6 query()方法

函数调用: qe = ses.query(*entities, **kwargs)

函数功能:利用会话对象对表格等数据进行查询操作,并返回一个新的Query对象

传入参数: *entities, **kwargs

entities: obj类型,需要查询的表格对象等

返回参数: qe

qe: obj类型,返回的Query对象

Note: 源代码的实现实际上是返回一个query.Query类实例

2.2.2.3 query模块

2.2.2.3.1 Query

类实例化: qe = ses.query(*entities, **kwargs) / Query(entities, session=None)

类的功能:生成一个Query实例

传入参数: *entities, **kwargs

entities: obj类型,需要查询的表格对象等

返回参数: qe

qe: obj类型,返回的一个Query类实例

       Link: http://docs.sqlalchemy.org/en/latest/orm/query.html

       Note: 通常Query的实例化使用session.query()函数来返回,少数情况下也可直接通过Query类进行生成

       E.g.:

qe = Query([User, Address], session=some_session)  
# The above is equivalent to::  
qe = some_session.query(User, Address)  

2.2.2.3.1.1 filter()方法

函数调用: nqe = qe.filter(*criterion)

函数功能:根据标准进行条件筛选,并返回一个筛选后新的Query对象

传入参数: criterion

criterion: obj类型,条件查询表达式

返回参数: qe

qe: obj类型,返回的新Query对象

Note: 返回的是Query实例因此可以继续对其进行函数操作

E.g.: 

# Single criteria  
session.query(MyClass).filter(MyClass.name == 'some name')  
  
# Multiple criteria may be specified as comma separated; the effect  
# is that they will be joined together using the :func:`.and_`  
session.query(MyClass).filter(MyClass.name == 'some name', MyClass.id > 5)

2.2.2.3.1.2 filter_by()方法

函数调用: nqe = qe.filter(**kwargs)

函数功能:使用关键字表达式进行对象筛选

传入参数: kwargs

kwargs: obj类型,关键词条件查询表达式

返回参数: nqe

nqe: obj类型,返回的新Query对象

Note: 返回的是Query实例因此可以继续对其进行函数操作,关键字表达式会从首要的query对象中获取

E.g.:

# Single criteria  
session.query(MyClass).filter_by(name == 'some name')  
  
# Multiple criteria may be specified as comma separated; the effect  
# is that they will be joined together using the :func:`.and_`  
session.query(MyClass).filter_by(name == 'some name', id > 5) 

 

2.2.2.3.1.3 order_by()方法

函数调用: nqe = qe.order_by(*criterion)

函数功能:根据关键字进行排序

传入参数: criterion

criterion: obj类型,可传入某表列名

返回参数: nqe

nqe: obj类型,返回的新Query对象

 

2.2.3 .ext

2.2.3.1 ext.declarative模块

2.2.3.1.1 declarative_base()函数

函数调用: Base = declarative_base(**kwargs)

函数功能:为声明层的定义构建一个base类,基于Base类可以生成表格对象sqlalchemy.schema.Table,同时会使映射器函数sqlalchemy.orm.mapper调用时会提取类或其子类中的信息

传入参数: kwargs

返回参数: Base

Base: class类型,通常可以用作表格类的基类

 

2.2.4 .sql模块

2.2.4.1 sql.schema模块

2.2.4.1.1 Table

类实例化:mytable = Table(name, metadata, **kwargs)

类的功能:用于映射表示一个数据库中的表

传入参数: name, metadata, kwargs

name: str类型,数据库中对应映射的表名称

metadata: obj类型,MetaData对象将包含这张表,metadata将作为这张表与其他表通过外键连接的关键点,可传入Base.metadata

column: obj类型,由Column类生成的列实例,用于对应表中的列

返回参数: mytable

mytable: instance类型,生成的表对象实例

E.g.:

mytable = Table("mytable", metadata,  
                Column('mytable_id', Integer, primary_key=True),  
                Column('value', String(50))  
               )  

 

2.2.4.1.2 Column

类实例化:mycolumn = Column(name, type, primary_key=, **kwargs)

类的功能:用于生成一个列的类实例

传入参数: name, type, primary, kwargs

name: str类型,数据库中表的列名称

type: obj类型,数据库中表的列存储数据类型

primary_key: bool类型,用于设置主键

返回参数: mycolumn

mycolumn: instance类型,生成的列对象实例

Note: 根据源码说明,在传入name和type之后,可直接传入其余SchemaItem类,诸如ForeignKey, Constraint等等

 

2.2.4.1.3 ForeignKey

类实例化:fk= ForeignKey(column)

类的功能:用于生成外键

传入参数: column

column: obj/str类型,列的实例或列的名称

返回参数: fk

fk: instance类型,生成的外键实例对象

2.2.4.2 sql.sqltypes模块

2.2.4.2.1 Integer

类实例化:

类的功能:常用于列生成时传入的数据类型对象,等同于int/integers

传入参数:

返回参数:

 

2.2.4.2.2 VARCHAR

类实例化:

类的功能:常用于列生成时传入的数据类型对象,SQL VARCHAR类型

传入参数: string

string: str类型,VARCHAR的大小

返回参数:

 

2.2.5 .dialects模块

Note:

当在.sql.sqltype中找不到所需的数据类型时,可在此模块中进行获取,导入对于特定数据库,如MySQL, SQL Server等特有的数据类型的类对象进行使用

 

参考链接


 

http://www.sqlalchemy.org/

https://*.com/questions/30638003/connecting-to-database-using-sqlalchemy

https://*.com/questions/30025509/sqlalchemy-orm-styles-how-to-make-special-drive-to-your-connection-string

http://blog.csdn.net/fgf00/article/details/52949973

http://www.cnblogs.com/liu-yao/p/5342656.html

http://docs.sqlalchemy.org/en/latest/orm/query.html