我們?cè)趯慡QLAlchemy的時(shí)候, 通常定義好 數(shù)據(jù)庫(kù)表的類, 然后比如插入數(shù)據(jù), 就會(huì)先生成一個(gè)對(duì)象, 然后做插入操作, 或者是query得到一個(gè)對(duì)象, 即查詢結(jié)果.
在 session 中, 一個(gè)對(duì)象會(huì)有4個(gè)狀態(tài)
- Transient: 此時(shí)對(duì)象并不在session中, 而且沒(méi)有保存到數(shù)據(jù)庫(kù)中, 比如剛新建的對(duì)象.
- Pending: 在調(diào)用add()時(shí), 傳入一個(gè)Transient狀態(tài)的對(duì)象, 那個(gè)對(duì)象的狀態(tài)改為Pending.
- Persistent: 一個(gè)對(duì)象存在于session, 且和數(shù)據(jù)庫(kù)中的某一行對(duì)應(yīng).(比如query得到的結(jié)果)
- Detached: 對(duì)象和數(shù)據(jù)庫(kù)中的一條數(shù)據(jù)對(duì)應(yīng), 但不在任何session中. 在commit之后, 所有的對(duì)象狀態(tài)都變成Detached.
還有個(gè) deleted, 是version1.1新增的狀態(tài).
一個(gè)對(duì)象從進(jìn)入session 到 離開(kāi)session, 通常要經(jīng)過(guò)這4個(gè)過(guò)程.
from sqlalchemy import inspect
one = User("a", "b")
insp = inspect(one)
insp.transient
# Out[10]: True
insp.pending
# Out[11]: False
db.session.add(one)
insp.pending
# Out[13]: True
insp.transient
# Out[14]: False
db.session.commit()
insp.persistent
# Out[19]: True
session 會(huì)重點(diǎn)跟蹤Pending狀態(tài)的對(duì)象, 對(duì)于persistent的對(duì)象, 因?yàn)樗硎緦?duì)象和數(shù)據(jù)庫(kù)中的數(shù)據(jù)已經(jīng)一致, 那么這個(gè)對(duì)象隨時(shí)可以從 session 去丟棄. 那么問(wèn)題是 何時(shí)丟棄?
丟的太早, 用戶如果剛好要查詢剛剛插入的數(shù)據(jù), 那么又得從數(shù)據(jù)庫(kù)中讀取一次; 如果丟的太晚, 大量對(duì)象會(huì)囤積在內(nèi)存中. 于是這件事情就交給了 垃圾回收.
session 中的對(duì)象都有一個(gè)weakref(弱引用), 會(huì)被垃圾回收強(qiáng)制回收.
為了保證padding狀態(tài)的數(shù)據(jù)不被強(qiáng)制回收, 用強(qiáng)引用保存它們, 在session的new, dirty, deleted屬性中可以看到."new表示剛剛被加入會(huì)話的對(duì)象,dirty屬性表示剛剛被修改的對(duì)象,而deleted屬性表示在會(huì)話中被刪除的對(duì)象"
one = User("a","b")
db.session.add(one)
print(db.session.new)
# Out[27]: IdentitySet([User: a])