sqlalchmey (1)

Fork from CSDN
基本概念

说到数据库,就离不开Session。Session的主要目的是建立与数据库的会话,它维护你加载和关联的所有数据库对象。它是数据库查询(Query)的一个入口。

在Sqlalchemy中,数据库的查询操作是通过Query对象来实现的。而Session提供了创建Query对象的接口。

Query对象返回的结果是一组同一映射(Identity Map)对象组成的集合。事实上,集合中的一个对象,对应于数据库表中的一行(即一条记录)。所谓同一映射,是指每个对象有一个唯一的ID。如果两个对象(的引用)ID相同,则认为它们对应的是相同的对象。
要完成数据库查询,就需要建立与数据库的连接。这就需要用到Engine对象。一个Engine可能是关联一个Session对象,也可能关联一个数据库表。
当然Session最重要的功能还是实现原子操作。

创建Session

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

some_engine = create_engine('nysql://username:password@localhost/mydb?charset=utf8')

ession = sessionmaker(bind=some_engine)

session = Session()

代码第4行创建一个Engine对象,我们提供的参数是数据库连接的url。
代码第6行通过sessionmaker方法创建了一个Session工厂。
代码第8行通过调用工厂方法来创建一个Session对象。

Session的生命期

Session通常在我们需要对数据库进行操作时创建。
一旦一个Session创建成功,我们在这个Session下完成多个事务(transaction)。
究竟何时创建和关闭session,不能一概而论。但是一个原则是session不应该在操作事务的方法中创建。

例如下面的方法定义就是不规范的。

class SomeThing(object):
    def go(self):
        session = Session()
        try:
            # Do something
            session.commit()
        except:
            session.rollback()
            raise

The correct code is here:

class SomeThing(object):
    def go(self, session):
        # Do something

def run_my_program():
    session = Session()
    try:
        SomeThing().go(session)
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

以下摘自sqlalchmey docs:

Session Basics

  • What does the Session do ?

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 entry-point (指令变换点)to acquire a Query
object, __which sends queries to the database using the Session
object’s current database connection (通过当前session object的数据库连接发送query请求), __populating result rows into objects that are then stored in the Session
, (将存储在 Session 中的 result rows 迁移到 objects 中)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”.

The Session
begins in an essentially stateless(无状态的) form. Once queries are issued or other objects are persisted with it, it requests a connection resource from an Engine
that is associated either with the Session
itself or with the mapped Table
objects being operated upon.(一个与Session关联或者与 Table 映射的数据库 engine是必须的) This connection represents an ongoing transaction, which remains in effect until the Session
is instructed to commit or roll back its pending state (这个连接表示一个不断进行的事务,它会一直起效直到 Session 被执行commit 或者回滚到之前的 pending 状态).

All changes to objects maintained by a Session
are tracked (所有由session维护,并对objects的改变,都会被追踪)- before the database is queried again or before the current transaction is committed, (在再一次查询数据库 或 当前事务被提交 之前), it flushes all pending changes to the database. This is known as the Unit of Work pattern.

Unit of work : A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.

When using a Session
, it’s important to note that the objects which are associated with it are proxy objects(代理 objects) to the transaction being held by the Session
- there are a variety of events that will cause objects to re-access the database in order to keep synchronized (存在很多的事件会导致objects 重复连接数据库,为了保持同步性). It is possible to “detach” objects from a Session
, and to continue using them, though this practice has its caveats(警告). It’s intended that usually, you’d re-associate detached objects with another Session
when you want to work with them again, (所以需要通过其他的Session 重新联系已分发的objects,如果你想要重新使他们工作)so that they can resume their normal task of representing database state.

Getting a Session

Session
is a regular Python class which can be directly instantiated(直接实例化). However, to standardize how sessions are configured and acquired, the sessionmaker
class is normally used to create a top level Session
configuration which can then be used throughout an application without the need to repeat the configurational arguments(使用sessionmaker,无需重新配置session).

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# an Engine, which the Session will use for connection
# resources
some_engine = create_engine('postgresql://scott:tiger@localhost/') #数据库的链接

# create a configured "Session" class
Session = sessionmaker(bind=some_engine)

# create a Session
session = Session()

# work with sess
myobject = MyObject('foo', 'bar')
session.add(myobject)
session.commit()

Above, the sessionmaker
call creates a factory for us, which we assign to the name Session
This factory, when called, will create a new Session
object using the configurational arguments we’ve given the factory. In this case, as is typical, we’ve configured the factory to specify a particular Engine
for connection resources.

A typical setup will associate the sessionmaker with an Engine, so that each Session generated will use this Engine to acquire connection resources. (生成的每个 Session 都通过engine来获取连接资源) This association can be set up as in the example above, using the bind argument.

When you write your application, place the sessionmaker
factory at the global level(设置sessionmaker到全局层面). This factory can then be used by the rest of the application as the source of new Session
instances, keeping the configuration for how Session
objects are constructed in one place.

The sessionmaker
factory can also be used in conjunction with other helpers, which are passed a user-defined sessionmaker
that is then maintained by the helper. Some of these helpers are discussed in the section When do I construct a Session, when do I commit it, and when do I close it?.(sessionmaker还可以自定义)

Adding Additional Configuration to an Existing sessionmaker()

A common scenario is where the sessionmaker
is invoked (被调用)at module import time, however the generation of one or more Engine
instances to be associated with the sessionmaker
has not yet proceeded.(一个常见的情况是,sessionmaker通常在模块被导入时就被调用,但与sessionmaker耦合的engine还没有生成) For this use case, the sessionmaker
construct offers the sessionmaker.configure()
method, which will place additional configuration directives into an existing sessionmaker
that will take place when the construct is invoked(在construct被调用时,configure()会将额外的配置指令加入到已经存在的session-maker中):

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

# configure Session class with desired options
Session = sessionmaker()

# later, we create the engine
engine = create_engine('postgresql://...')

# associate it with our custom Session class
Session.configure(bind=engine)

# work with the session
session = Session()

Creating Ad-Hoc Session Objects with Alternate Arguments

For the use case where an application needs to create a new Session
with special arguments that deviate from what is normally used throughout the application, such as a Session
that binds to an alternate source of connectivity, or a Session
that should have other arguments such as expire_on_commit
established differently from what most of the application wants, specific arguments can be passed to the sessionmaker
factory’s sessionmaker.call()
method. These arguments will override(废除) whatever configurations have already been placed, such as below, where a new Session
is constructed against a specific Connection
:

# at the module level, the global sessionmaker,
# bound to a specific Engine
Session = sessionmaker(bind=engine)

# later, some unit of code wants to create a
# Session that is bound to a specific Connection
conn = engine.connect()
session = Session(bind=conn)

The typical rationale for the association of a Session
with a specific Connection
is that of a test fixture that maintains an external transaction - see Joining a Session into an External Transaction (such as for test suites) for an example of this.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容