sqlalchemy 里的 session 具体有啥作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sqlalchemy 里的 session 具体有啥作用相关的知识,希望对你有一定的参考价值。

官网有写,不过看的不是很懂。
大致意思是Session用于创建程序与数据库之间的会话,并将这个会话以python的面向对象方式(“holding zone”)进行包装,提供给python其他程序调用。
Session提供一个进行数据库查询(query)的入口,python程序通过Session实例,可以对正在连接的数据库进行查询(查询结果是一个面向对象实例),将修改的内容(一般是修改面向对象实例,然后通过Session将修改的实例与数据库中特定数据“同步”。)
Session中有一个很重要的理念“Identity Map”。Session查询的结果实例,我们修改过的实例,和数据库中的数据是怎么关联起来的呢?就是靠“Identity Map”,每个实例都具有“Identity Map”记录,每个“Identity Map”都和数据行的主键(primary key)一一对应。

(这是我的渣英语翻译+个人理解写的。有不对的地方,欢迎大神指点)

官网内容:
In the most general sense, the Session establishes all conversations with the database and represents a “holding zone” for all the objects which you’ve loaded or associated with it during its lifespan. It provides the entrypoint to acquire a Query object, which sends queries to the database using the Session object’s current database connection, populating result rows into objects that are then stored in the Session, inside a structure called the Identity Map - a data structure that maintains unique copies of each object, where “unique” means “only one object with a particular primary key”.

官网资料:http://docs.sqlalchemy.org/en/rel_0_9/orm/session_basics.html#what-does-the-session-do
参考技术A 保持mysql连接不中断的意思、、跟http的会话大概一个意思。

SQLAlchemy最佳实践:何时/如何配置scoped_session?

我试图找出正确的方法来使用SQLAlchemy范围会话“正确的方式”,同时保持定义会话的逻辑与配置分开并与使用会话分开。有人告诉我,有一个很好的方法是建立一个全球scoped_session工厂,我可以随处使用:

"""myapp/db.py
"""

from sqlalchemy.orm import sessionmaker, scoped_session

Session = scoped_session(sessionmaker())

然后,当我想使用它时:

"""myapp/service/dosomething.py
"""

from myapp.db import Session

def do_something(data): 
    """Do something with data
    """
    session = Session()
    bars = session.query(Bar).all()
    for bar in bars:
        bar.data = data
    session.commit()

这似乎是正确的,但我的问题是,在我看到的所有示例中,sessionmaker还会设置会话的一些参数,即最重要的是绑定引擎。这对我来说毫无意义,因为实际的数据库引擎将在导入myapp.db模块期间从全局范围内未知的配置创建。

我所看到的是在我的应用程序的“主”(或线程的主函数)中设置所有内容,然后假设会话在其他地方配置(例如上面的do_something()使用时):

"""myapp/main.py
"""

from sqlalchemy import create_engine
from myapp.db import Session
from myapp.service.dosomething import do_something

def main(): 
    config = load_config_from_file()
    engine = create_engine(**config['db'])
    Session.configure(bind=engine)

    do_something(['foo', 'bar'])

这看起来像是一种正确的方法吗?我没有找到任何这种流程的好例子,但我发现的大多数其他例子似乎都过于简化或特定于框架。

答案

你可以做的是将配置分成一个单独的模块:

"""myapp/cfg.py
"""
config = load_config_from_file()

然后您可以在任何需要的地方导入此文件,包括在db模块中,这样您就可以构建引擎以及会话:

"""myapp/db.py
"""
from .cfg import config
engine = create_engine(**config['db'])
Session = scoped_session(sessionmaker(bind=engine))
另一答案

想想单身人士。在你的情况下from myapp.db import Session,Session是单身和全球的。只需在应用程序的开头配置Session即可。您应该有一个配置过程,如从文件或env加载配置数据,在所有配置准备就绪后,运行真实程序。

以上是关于sqlalchemy 里的 session 具体有啥作用的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy:直接从一对多关系中删除对象,而不使用 session.delete()

Flask-Session SQLAlchemy Script Migrate wtforms

Flask-Session SQLAlchemy Script Migrate wtforms

SQLAlchemy最佳实践:何时/如何配置scoped_session?

SQLAlchemy 中的 Sessionsessionmakerscoped_session

使用SQLAlchemy更新对象