SQLAlchemy 和其他的 ORM 框架

發表於2016-01-12

Python ORM 概覽

作為一個美妙的語言,Python 除了 SQLAlchemy 外還有很多ORM庫。在這篇文章裡,我們將來看看幾個流行的可選 ORM 庫,以此更好地窺探到Python ORM 境況。通過寫一段指令碼來讀寫2個表 ,person 和 address 到一個簡單的資料庫,我們能更好地理解每個ORM庫的優缺點。

SQLObject

SQLObject 是一個介於SQL資料庫和Python之間對映物件的Python ORM。得益於其類似於Ruby on Rails的ActiveRecord模式,在程式設計社群變得越來越流行。首個 SQLObject在2002年十月釋出。它遵循LGPL許可。

在 SQLObject 中,資料庫概念是通過與 SLQAlchemy 非常類似的的一種方式對映到Python的,表對映成類,行作為例項而欄位作為屬性。它同時提供一種基於Python物件的查詢語言,這使得 SQL 更加抽象, 從而為應用提供了資料庫不可知性(譯註:應用和資料庫分離)。

 

上面的程式碼建立了2個簡單的表:person 和 address 。為了建立和插入記錄到這2個表,我們簡單例項化一個person 例項和 一個 address 例項:

為了獲得或檢索新記錄, 我們用神奇的 q 物件關聯到 Person 和 Address 類:

Storm

Storm 是一個介於 單個或多個資料庫與Python之間 對映物件的 Python ORM 。為了支援動態儲存和取回物件資訊,它允許開發者構建跨資料表的複雜查詢。它由Ubuntu背後的公司 Canonical公司用Python開發的,用在 Launchpad 和 Landscape 應用中,後來在2007年作為自由軟體釋出。這個專案在LGPL許可下發布,程式碼貢獻者必須受讓版權給Canonical公司。

像 SQLAlchemy 和 SQLObject 那樣, Storm 也對映表到類,行到例項和欄位到屬性。相對另外2個庫, Stom中 table class 不需要是框架特定基類 的子類 。在 SQLAlchemy中,每個 table class 是 sqlalchemy.ext.declarative.declarative_bas 的一個子類。 而在SQLOjbect中,每個table class是 的 sqlobject.SQLObject 的子類。

類似於 SQLAlchemy, Storm 的 Store 物件對於後端資料庫就像一個代理人, 所有的操作快取在記憶體,一當提交方法在store上被呼叫就提交到資料庫。每個 store 持有自己的Python資料庫物件對映集合,就像一個 SQLAlchemy session 持有不同的 Python物件集合。

指定版本的 Storm 可以從 下載頁面 下載。在這篇文章裡,示例程式碼是使用 0.20 版本的Storm寫的。

上面的程式碼建立了一個 sqlite 記憶體資料庫,然後用 store 來引用該資料庫物件。一個Storm store 類似 SQLAlchemy的 DBSession物件,都管理 附屬於其的例項物件 的生命週期。例如,下面的程式碼建立了一個 person 和 一個 address, 然後通過重新整理 store 都插入記錄。

為了獲得或檢索已插的 Person 和 Address 物件, 我們呼叫 store.find() 來查詢:

Django 的 ORM

Django 是一個免費開源的緊嵌ORM到其系統的web應用框架。在它首次釋出後,得益於其易用為Web而備的特點,Django越來越流行。它在2005年七月在BSD許可下發布。因為Django的ORM 是緊嵌到web框架的,所以就算可以也不推薦,在一個獨立的非Django的Python專案中使用它的ORM。

Django,一個最流行的Python web框架, 有它獨有的 ORM。 相比 SQLAlchemy, Django 的 ORM 更吻合於直接操作SQL物件,操作暴露了簡單直接對映資料表和Python類的SQL物件 。

因為我們在沒有先建立一個專案時不能夠執行Django程式碼,所以我們在前面的shell建立一個Django demo 專案,然後進入Django shell來測試我們寫的 ORM 例子。

上面的程式碼宣告瞭2個Python 類,Person 和 Address,每一個都對映到資料庫表。在執行任意資料庫操作程式碼之前,我們需要先在本地的sqlite資料庫建立表。

為了插入一個 person 和一個 address 到資料庫,我們例項化相應物件並呼叫這些物件的save() 方法。

為了獲得或檢索 person 和 address 物件, 我們用model類神奇的物件屬性從資料庫取得物件。

peewee

peewee 是一個小的,表示式的 ORM。相比其他的 ORM,peewee 主要專注於極簡主義,其API簡單,並且其庫容易使用和理解。

為了建立資料庫模型對映,我們實現了一個Person 類 和一個Address類 來對映對應的資料庫表。

為了插入物件到資料庫,我們例項化物件並呼叫了它們的save() 方法。從檢視的物件建立這點來看,peewee類似於Django。

為了從資料庫獲得或檢索物件, 我們select 了類各自的物件。

SQLAlchemy

SQLAlchemy 是Python程式語言裡,一個在MIT許可下發布的開源工具和SQL ORM。它首次釋出於2006年二月,由Michael Bayer寫的。它提供了 “一個知名企業級的持久化模式的,專為高效率和高效能的資料庫訪問設計的,改編成一個簡單的Python域語言的完整套件”。它採用了資料對映模式(像Java中的Hibernate)而不是Active Record模式(像Ruby on Rails的ORM)。

SQLAlchemy 的工作單元 主要使得 有必要限制所有的資料庫操作程式碼到一個特定的資料庫session,在該session中控制每個物件的生命週期 。類似於其他的ORM,我們開始於定義declarative_base()的子類,以對映表到Python類。

在我們寫任何資料庫程式碼前,我們需要為資料庫session建立一個資料庫引擎。

一當我們建立了資料庫引擎,可以繼續建立一個資料庫會話,併為所有之前定義的 Person和Address 類建立資料庫表。

現在,session 物件物件變成了我們工作單元的建構函式,將和所有後續資料庫操作程式碼和物件關聯到一個通過呼叫它的 __init__() 方法構建的資料庫session上。

為了獲得或檢索資料庫中的物件,我們在資料庫session物件上呼叫 query() 和 filter() 方法。

請留意到目前為止,我們還沒有提交任何對資料庫的更改,所以新的person和address物件實際上還沒儲存在資料庫中。 呼叫 s.commit() 將會提交更改,比如,插入一個新的person和一個新的address到資料庫中。

Python ORM 之間對比

對於在文章裡提到的每一種 Python ORM ,我們來列一下他們的優缺點:

SQLObject

優點:

  1. 採用了易懂的ActiveRecord 模式
  2. 一個相對較小的程式碼庫

缺點:

  1. 方法和類的命名遵循了Java 的小駝峰風格
  2. 不支援資料庫session隔離工作單元

Storm

優點:

  1. 清爽輕量的API,短學習曲線和長期可維護性
  2. 不需要特殊的類建構函式,也沒有必要的基類

缺點:

  1. 迫使程式設計師手工寫表格建立的DDL語句,而不是從模型類自動派生
  2. Storm的貢獻者必須把他們的貢獻的版權給Canonical公司

Django’s ORM

優點:

  1. 易用,學習曲線短
  2. 和Django緊密集合,用Django時使用約定俗成的方法去運算元據庫

缺點:

  1. 不好處理複雜的查詢,強制開發者回到原生SQL
  2. 緊密和Django整合,使得在Django環境外很難使用

peewee

優點:

  1. Django式的API,使其易用
  2. 輕量實現,很容易和任意web框架整合

缺點:

  1. 不支援自動化 schema 遷移
  2. 多對多查詢寫起來不直觀

SQLAlchemy

優點:

  1. 企業級 API,使得程式碼有健壯性和適應性
  2. 靈活的設計,使得能輕鬆寫複雜查詢

缺點:

  1. 工作單元概念不常見
  2. 重量級 API,導致長學習曲線

總結和提示

相比其他的ORM, SQLAlchemy 意味著,無論你何時寫SQLAlchemy程式碼, 都專注於工作單元的前沿概念 。DB Session 的概念可能最初很難理解和正確使用,但是後來你會欣賞這額外的複雜性,這讓意外的時序提交相關的資料庫bug減少到0。在SQLAlchemy中處理多資料庫是棘手的, 因為每個DB session 都限定了一個資料庫連線。但是,這種型別的限制實際上是好事, 因為這樣強制你絞盡腦汁去想在多個資料庫之間的互動, 從而使得資料庫互動程式碼很容易除錯。

在未來的文章中,我們將會完整地披露更高階的SQLAlchemy用例, 真正領會無限強大的API。

相關文章