1. 添加一個新對象
前面介紹了映射到實體表的映射類User,如果我們想將其持久化(Persist),那么就需要將這個由User類建立的對象實例添加到我們先前創建的Session會話實例中:
代碼如下:
ed_user = User('ed', 'Ed Jones', 'edspassword')
session.add(ed_user)
上面兩段代碼執行完后對象持久化了么?你或許會興沖沖的跑去數據庫里查看,結果卻失望而歸——數據庫里什么都沒有。為什么呢?因為SQLAlchemy采取的是Lazyload策略,也就是說現在這個對象被標記為Pending準備狀態,但沒有執行任何可能導致數據庫變化的SQL語句。那么什么時候會執行SQL語句并真正持久化呢?這個要等SQLAlchemy覺得需要的時候,比如我們現在查詢這個對象、對象的一個屬性或者顯式的調用flush方法,這時候SQLAlchemy覺得它“是時候”或者“不得不”執行SQL數據庫查詢以便于把標記為Pending的數據寫入數據庫表中了。假如這時候你執行的獲取對象、對象屬性或者類似的操作,SQLAlchemy在執行完SQL語句后會將你所要查詢的數據反饋給你。
為了更好的說明這一點,這里舉一個例子,這里涉及到我們第一個查詢示例,我們調用了Query對象來幫助我們完成這些,比如這里我們獲取剛剛持久化的用戶ed,我們通過“過濾(filter by)”的方式來查詢用戶名為ed的用戶,當然我們只需要一個ed,假如有多個重名的ed的話,查詢將會返回所有叫ed的記錄集列表,我們就選擇第一個ed吧(first)。
代碼如下:
>>> our_user = session.query(User).filter_by(name='ed').first()
BEGIN (implicit)
INSERT INTO users (name, fullname, password) VALUES (?, ?, ?)
('ed', 'Ed Jones', 'edspassword')
SELECT users.id AS users_id,
users.name AS users_name,
users.fullname AS users_fullname,
users.password AS users_password
FROM users
WHERE users.name = ?
LIMIT ? OFFSET ?
('ed', 1, 0)
>>> our_user
<User('ed','Ed Jones', 'edspassword')>
可以看到上面的查詢語句返回了一個User的實例,而這個實例恰恰是我們先前持久化的。同時由于我們指定了引擎的echo=True,所以再執行查詢時輸出了SQL語句,我們注意到除了普通的SELECT外,還有額外的INSERT語句,而INSERT處理的就是我們剛剛通過session.add()持久化標記為Pending的對象,也就是說你在實際操作持久化數據時才會由延遲加載(lazyload)真正觸發數據庫操作。
實際上Session查詢反饋給我們的User對象和我們剛剛持久化的對象是同一個對象,通過下面的代碼可以檢驗:
代碼如下:
>>> ed_user is our_user
True
實際上這里ORM的操作概念有點類似于標識映射(identity map),也就是說在實體數據庫之前架設一張標識映射表,可以看作緩存表的一種,任何存儲數據庫的對象會事先停留在這張表上,如果我們要查詢一個對象,將事先查詢這張標識映射表,如果這個對象存在則直接取出,否則就會查詢實體數據庫,我覺得這個有點像緩存的作用,可以這么理解吧。
新聞熱點
疑難解答