作者:Michael Bayer
譯者:謝路云
狀態(tài):翻譯中
SQLAlchem??y是一個(gè)Python語(yǔ)言的數(shù)據(jù)庫(kù)工具包和關(guān)系對(duì)象映射(ORM)系統(tǒng),始于2005年。從一開(kāi)始,它就力求通過(guò)Python的數(shù)據(jù)庫(kù)API(即DBAPI)提供一種和關(guān)系數(shù)據(jù)庫(kù)交互的端對(duì)端系統(tǒng)。從早期的版本開(kāi)始,SQLAlchemy的功能就吸引了很多人的注意力。它的主要特性包括能夠流暢的表達(dá)復(fù)雜的SQL查詢和對(duì)象映射,以及實(shí)現(xiàn)了"Unit of Work"模式來(lái)高度自動(dòng)化的完成數(shù)據(jù)在數(shù)據(jù)庫(kù)中的持久化。
從一個(gè)渺小而粗糙的概念性實(shí)現(xiàn)開(kāi)始,SQLAlchemy迅速經(jīng)歷了一系列蛻變和打磨。隨著用戶群的增長(zhǎng),內(nèi)部架構(gòu)和公共API也在不斷的迭代。到了2009年一月發(fā)布0.5版本之時(shí),SQLAlchemy已經(jīng)在大量的生產(chǎn)環(huán)境中部署并證明了自己,并開(kāi)始穩(wěn)定下來(lái)。0.6(2010年四月)和0.7(2011年五月)兩個(gè)版本對(duì)架構(gòu)和API的改進(jìn)使我們成為了最高效和最穩(wěn)定的第三方庫(kù)。截至撰寫本文之時(shí),大量不同領(lǐng)域的組織都在使用SQLAlchem??y。它已經(jīng)被大家認(rèn)可并事實(shí)上成為使用Python操作關(guān)系型數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)庫(kù)。
“數(shù)據(jù)庫(kù)抽象層”通常指的是一種用來(lái)和數(shù)據(jù)庫(kù)通訊并隱藏?cái)?shù)據(jù)的存儲(chǔ)和查詢的大部分細(xì)節(jié)的系統(tǒng)。對(duì)這個(gè)詞的理解有時(shí)會(huì)走向一個(gè)極端,認(rèn)為這樣的系統(tǒng)應(yīng)該隱藏的不僅是所使用的關(guān)系數(shù)據(jù)庫(kù)的細(xì)節(jié),還應(yīng)該包括數(shù)據(jù)的關(guān)系結(jié)構(gòu),甚至不再關(guān)心底層的存儲(chǔ)機(jī)制是否是基于關(guān)系的。
對(duì)于ORM最常見(jiàn)的批評(píng)認(rèn)為以上就是這種工具的最主要目的——把關(guān)系數(shù)據(jù)庫(kù)“藏起來(lái)”,接管和數(shù)據(jù)庫(kù)的交互并將它們轉(zhuǎn)化為實(shí)現(xiàn)的細(xì)節(jié)。這種方式的核心意義在于將設(shè)計(jì)和查詢關(guān)系數(shù)據(jù)結(jié)構(gòu)的工作從開(kāi)發(fā)者轉(zhuǎn)移到一個(gè)不透明的第三方庫(kù)中。
經(jīng)常和關(guān)系數(shù)據(jù)庫(kù)打交道的人都知道,這種認(rèn)識(shí)完全是不切實(shí)際的。關(guān)系結(jié)構(gòu)和SQL查詢都是功能性的,它們組成了一個(gè)應(yīng)用程序設(shè)計(jì)的核心。應(yīng)該如何在查詢中設(shè)計(jì)、組織和操作這些結(jié)構(gòu)不僅取決于要查詢哪些數(shù)據(jù),也取決于數(shù)據(jù)的結(jié)構(gòu)。如果連這些信息都要隱藏起來(lái),那么也就根本沒(méi)有使關(guān)系數(shù)據(jù)庫(kù)的必要了。
既要滿足應(yīng)用程序屏蔽底層關(guān)系數(shù)據(jù)庫(kù)復(fù)雜性的期望,又要滿足使用關(guān)系數(shù)據(jù)庫(kù)所必要的繁復(fù),這種矛盾被稱為“對(duì)象-關(guān)系的阻抗不匹配”問(wèn)題。SQLAlchem??y采用了一些新穎的方法來(lái)解決這個(gè)問(wèn)題。
SQLAlchem??y的數(shù)據(jù)庫(kù)抽象層
SQLAlchem??y認(rèn)為開(kāi)發(fā)人員必須要考慮他或者她的數(shù)據(jù)的關(guān)系形式。預(yù)判并隱藏?cái)?shù)據(jù)庫(kù)schema和查詢的系統(tǒng)所設(shè)計(jì)的行為只會(huì)降低使用關(guān)系數(shù)據(jù)庫(kù)的必要性,進(jìn)而導(dǎo)致阻抗不匹配所帶來(lái)的一系列經(jīng)典問(wèn)題。(*)
但同時(shí),這些行為的實(shí)現(xiàn)應(yīng)該也必須執(zhí)行在一個(gè)盡可能高的層次上。將一個(gè)對(duì)象模型和一個(gè)schema關(guān)聯(lián)起來(lái)并通過(guò)SQL語(yǔ)句將對(duì)象持久化是一項(xiàng)重復(fù)性極高的任務(wù)。使用工具來(lái)將這些任務(wù)自動(dòng)化才能開(kāi)發(fā)出更加簡(jiǎn)潔、高效和強(qiáng)大的應(yīng)用程序。而手動(dòng)實(shí)現(xiàn)這些操作的應(yīng)用程序所需的開(kāi)發(fā)時(shí)間將會(huì)是它的數(shù)倍。(*)
因此,SQLAlchemy對(duì)自己的定位是一個(gè)工具包 ,這是為了強(qiáng)調(diào)開(kāi)發(fā)者才是所有關(guān)系結(jié)構(gòu)以及這些結(jié)構(gòu)和應(yīng)用程序之間的聯(lián)系的設(shè)計(jì)者和構(gòu)造者,而不是第三方庫(kù)的盲目使用者。通過(guò)開(kāi)放“關(guān)系”,SQLAlchem??y實(shí)現(xiàn)的理念是“不完全抽象”,(*)它不利開(kāi)發(fā)者在應(yīng)用程序和關(guān)系數(shù)據(jù)庫(kù)之間自定義一個(gè)自動(dòng)化的交互層。SQLAlchem??y的創(chuàng)新在于它能夠在不犧牲對(duì)關(guān)系數(shù)據(jù)庫(kù)的控制能力的前提下做到高度的自動(dòng)化。
為了達(dá)到工具包這個(gè)目標(biāo),SQLAlchem??y將與數(shù)據(jù)庫(kù)交互的每一層都開(kāi)放成為了一組成熟的API,這產(chǎn)生了兩種主要的交互方式,分別是核心層(Core)和對(duì)象關(guān)系映射層(ORM)。核心層負(fù)責(zé)和Python的數(shù)據(jù)庫(kù)API(DBAPI)的交互、拼接數(shù)據(jù)庫(kù)能夠理解的SQL語(yǔ)句并管理schema。這些功能都對(duì)應(yīng)著公開(kāi)的API。
圖20.1的SQLAlchem??y的層圖
核心/ ORM SQLAlchem??y的分離一直是最本質(zhì)的特征,它既有優(yōu)點(diǎn)和缺點(diǎn)。目前在SQLAlchem??y的明確的核心導(dǎo)致ORM到關(guān)系數(shù)據(jù)庫(kù)映射類的屬性結(jié)構(gòu)被稱為一個(gè)Table ,而不是直接將其字符串表示在數(shù)據(jù)庫(kù)中的列名,產(chǎn)生一個(gè)SELECT查詢使用結(jié)構(gòu)稱為select ,而不是拼湊對(duì)象的屬性直接轉(zhuǎn)換成字符串聲明和接收結(jié)果行通過(guò)的的門面被稱為ResultProxy ,透明映射的select 每個(gè)結(jié)果行,而不是將數(shù)據(jù)直接從數(shù)據(jù)庫(kù)游標(biāo)一個(gè)用戶定義的對(duì)象。
核心元素的一個(gè)非常簡(jiǎn)單的ORM為中心的應(yīng)用程序是不可見(jiàn)的。但是,為核心的精心整合的ORM,讓流動(dòng)的過(guò)渡在ORM和核心之間的結(jié)構(gòu),更復(fù)雜的ORM為中心的應(yīng)用可以“向下移動(dòng)”,以便處理與數(shù)據(jù)庫(kù)中的更多的水平或兩個(gè)具體和微調(diào)的方式,隨著形勢(shì)的需要。SQLAlchem??y的有成熟,核心API已經(jīng)變得不那么明確經(jīng)常使用的ORM繼續(xù)提供更復(fù)雜和更全面的圖案。但是,核心的可用性也是一個(gè)貢獻(xiàn)SQLAlchem??y的早期成功的,因?yàn)樗试S早期的用戶來(lái)完成,更比可能的ORM仍在發(fā)展。
的ORM /核心方法的缺點(diǎn)是,指示必須穿越更多的步驟。Python的傳統(tǒng)的C實(shí)現(xiàn)有一個(gè)顯著的開(kāi)銷處罰為獨(dú)立的功能調(diào)用,這是主要原因在運(yùn)行時(shí)緩慢。傳統(tǒng)方法的改善這包括縮短呼叫通過(guò)重排鏈和內(nèi)聯(lián)與C代碼,并更換性能的關(guān)鍵領(lǐng)域。SQLAlchem??y的已經(jīng)花了多年使用這兩種方法提高性能。然而,越來(lái)越多的人接受的PyPy為Python解釋器可壁球余下的承諾性能問(wèn)題,而不需要更換的多數(shù)SQLAlchem??y的內(nèi)部結(jié)構(gòu)與C語(yǔ)言代碼,PyPy大大剛剛在時(shí)間的調(diào)用鏈長(zhǎng)通過(guò)減少的影響內(nèi)聯(lián)和編譯。
在該基地的SQLAlchem??y的是一個(gè)系統(tǒng)與數(shù)據(jù)庫(kù)進(jìn)行交互,通過(guò)DBAPI。DBAPI本身是不是一個(gè)實(shí)際的庫(kù),只有規(guī)范。因此,實(shí)現(xiàn)的DBAPI是可用于特別是目標(biāo)數(shù)據(jù)庫(kù),如MySQL或PostgreSQL,或者特別是非DBAPI,如ODBC和JDBC數(shù)據(jù)庫(kù)適配器。
的DBAPI提出了兩方面的挑戰(zhàn)。第一是提供一種易于使用且功能齊全的門面周圍的DBAPI的最基本的使用模式。二是要處理的變量的性質(zhì)具體的DBAPI的實(shí)現(xiàn),以及底層的數(shù)據(jù)庫(kù)引擎。 方言系統(tǒng)
由DBAPI接口是非常簡(jiǎn)單的。其核心部件DBAPI模塊本身,連接對(duì)象,并且將光標(biāo)對(duì)象的“光標(biāo)”數(shù)據(jù)庫(kù)中的說(shuō)法表示的上下文中特別聲明以及其相關(guān)的結(jié)果。一個(gè)簡(jiǎn)單的互動(dòng)與這些對(duì)象連接和檢索數(shù)據(jù)庫(kù)中的數(shù)據(jù)如下:
連接= dbapi.connect(用戶=“用戶”,PW =“私服”,主機(jī)=“主機(jī)”)光標(biāo)通過(guò)connection.cursor()cursor.execute(“SELECT * FROM user_table,其中name =?”(“杰克”,))打印列在“結(jié)果:”,說(shuō)明[0],描述在cursor.description]為排在cursor.fetchall():打印的“行”,行cursor.close()connection=close
SQLAlchem??y的創(chuàng)建一個(gè)門面周圍的經(jīng)典DBAPI談話?!包c(diǎn)進(jìn)入這個(gè)門面是create_engine電話,組裝連接和配置信息。一個(gè)實(shí)例作為結(jié)果產(chǎn)生的Engine 。該對(duì)象,然后網(wǎng)關(guān)DBAPI,這本身是永遠(yuǎn)不會(huì)直接暴露。
對(duì)于簡(jiǎn)單的語(yǔ)句執(zhí)行, Engine提供什么被稱為隱式執(zhí)行接口。本工作?獲取和關(guān)閉一個(gè)DBAPI連接和光標(biāo)在后臺(tái)處理:
引擎create_engine(“與postgresql :/ /用戶名:密碼:主機(jī)/數(shù)據(jù)庫(kù)”)結(jié)果engine.execute(“select * from表”)或打印result.fetchall(0)
SQLAlchemy的0.2的Connection對(duì)象補(bǔ)充說(shuō),提供的能力顯式地維護(hù)范圍的DBAPI連接:
康恩= engine.connect()專題專題查詢欄目位置(“select * from表”)或打印result.fetchall(0)conn.close()
返回的結(jié)果的execute方法的Engine 或Connection被稱為ResultProxy ,它提供了類似的DBAPI光標(biāo),但具有更豐富的接口行Engine ,Connection ,并ResultProxy對(duì)應(yīng)于DBAPI一個(gè)特定的模塊,例如DBAPI連接,和一個(gè)實(shí)例的一個(gè)特定的DBAPI光標(biāo)。
在幕后, Engine引用的對(duì)象所謂的Dialect 。Dialect是一個(gè)抽象的類存在許多實(shí)現(xiàn)的,每一個(gè)有針對(duì)性的在一個(gè)特定的的DBAPI /數(shù)據(jù)庫(kù)組合。創(chuàng)建一個(gè)ConnectionEngine代表將參照這個(gè)Dialect 可用于所有的決定,這取決于使用的目標(biāo)的DBAPI和數(shù)據(jù)庫(kù)可能具有不同的行為。
該Connection創(chuàng)建時(shí),從一個(gè)倉(cāng)庫(kù),采購(gòu)和維護(hù)的實(shí)際DBAPI連接被稱為一個(gè)Pool ,還與Engine相關(guān)聯(lián)的。Pool是負(fù)責(zé)創(chuàng)建新DBAPI連接的,通常情況下,他們保持經(jīng)常重復(fù)使用的內(nèi)存池。
在語(yǔ)句執(zhí)行期間,一個(gè)附加的對(duì)象被稱為ExecutionContext創(chuàng)建的Connection 。持續(xù)的對(duì)象點(diǎn)執(zhí)行的ResultProxy的整個(gè)生命周期。很顯然,那位同事是位多產(chǎn)教案,列表名單很大,所以教師選擇更先進(jìn)的搜索,并增加了也可以提供作為一個(gè)特定的子類的一些DBAPI /數(shù)據(jù)庫(kù)的組合。
圖20.2說(shuō)明了所有這些對(duì)象及其關(guān)系到每個(gè)以及其他的DBAPI組件。 圖20.2:發(fā)動(dòng)機(jī),連接,ResultProxy API 處理DBAPI變異
對(duì)于任務(wù)的管理DBAPI行為的變化,首先我們考慮問(wèn)題的范圍。在DBAPI在第二版規(guī)范,目前,寫的是一個(gè)系列API定義,允許廣泛的變異程度行為,并留下一個(gè)不確定的領(lǐng)域。其結(jié)果是,現(xiàn)實(shí)生活中的DBAPIs表現(xiàn)出很大程度的變化在若干領(lǐng)域,包括當(dāng)Python如何unicode字符串是可以接受的,當(dāng)他們都沒(méi)有;“最后插入的ID” - 這是一個(gè)自動(dòng)生成的主鍵可能是收購(gòu)后的INSERT語(yǔ)句,以及如何綁定參數(shù)值可以指定和解釋。他們也有大量面向類型的特質(zhì)的行為,包括二進(jìn)制處理,精度數(shù)值,日期,布爾和Unicode數(shù)據(jù)。
SQLAlchemy的接近允許在這兩個(gè)Dialect變化和ExecutionContext通過(guò)多層次的子類。如圖20.3所示Dialect之間的關(guān)系和ExecutionContext時(shí)用于與psycopg2的方言。PGDialect類的行為,特定的PostgreSQL數(shù)據(jù)庫(kù)的使用,如ARRAY數(shù)據(jù)類型和架構(gòu)目錄; PGDialect_psycopg2 類,然后提供特定的psycopg2的DBAPI的行為,包括Unicode數(shù)據(jù)處理程序和服務(wù)器端游標(biāo)的行為。 圖20.3:簡(jiǎn)單的方言/的ExecutionContext層次
上述模式的一個(gè)變體提出了自己在處理一個(gè)DBAPI支持多個(gè)數(shù)據(jù)庫(kù)。這方面的例子包括pyodbc,其中涉及任意數(shù)量的后端數(shù)據(jù)庫(kù)通過(guò)ODBC,和一個(gè)Jython與JDBC驅(qū)動(dòng)程序,其中涉及zxjdbc,。以上關(guān)系是增加了一個(gè)mixin類,從在使用sqlalchemy.connectors包提供DBAPI的行為,是常見(jiàn)的多個(gè)后端。圖20.4說(shuō)明了常見(jiàn)的功能sqlalchemy.connectors.pyodbc之間共享MySQL和Microsoft SQL Server的的pyodbc特定方言。 圖20.4:普通DBAPI方言層次之間共享的行為
Dialect ExecutionContext對(duì)象提供了一種手段定義與數(shù)據(jù)庫(kù)和DBAPI每一次互動(dòng),包括如何連接參數(shù)的格式和如何特殊在語(yǔ)句執(zhí)行期間被處理的怪癖。的Dialect 也是一個(gè)SQL編譯結(jié)構(gòu),使工廠SQL正確的目標(biāo)數(shù)據(jù)庫(kù),和類型的對(duì)象定義Python的數(shù)據(jù)應(yīng)如何封從目標(biāo)DBAPI和數(shù)據(jù)庫(kù)。 20.4。架構(gòu)定義
建立與數(shù)據(jù)庫(kù)的連接和交互性,接下來(lái)的任務(wù)提供創(chuàng)建和操縱的后端無(wú)關(guān)SQL語(yǔ)句。要做到這一點(diǎn),首先,我們需要確定我們將如何參照的表和列呈現(xiàn)在一個(gè)數(shù)據(jù)庫(kù)中的所謂的綱目表和列代表數(shù)據(jù)是有組織的,和大多數(shù)的SQL語(yǔ)句組成的表達(dá)式,參照這些結(jié)構(gòu)的命令。
一個(gè)的ORM或數(shù)據(jù)訪問(wèn)層需要提供編程訪問(wèn)SQL的語(yǔ)言,在該基地是一個(gè)編程的系統(tǒng)描述表。這是SQLAlchem??y的核心提供了第一個(gè)強(qiáng)大的部門ORM,提供的Table和Column的結(jié)構(gòu)描述數(shù)據(jù)庫(kù)的結(jié)構(gòu)獨(dú)立于用戶的模型類確定目標(biāo)背后的分工模式定義對(duì)象關(guān)系映射的關(guān)系架構(gòu)可以設(shè)計(jì)明確的關(guān)系型數(shù)據(jù)庫(kù),包括特定于平臺(tái)的沒(méi)有被混亂的對(duì)象 - 關(guān)系的概念,這些細(xì)節(jié),如果有必要,仍然是一個(gè)單獨(dú)的關(guān)注。作為獨(dú)立的的ORM成分也架構(gòu)描述系統(tǒng)是一樣有用的任何其他類型的對(duì)象 - 關(guān)系系統(tǒng)可建立在核心。
Table和Column模型屬于的范圍是什么被稱為元數(shù)據(jù) ,提供一個(gè)集合對(duì)象的MetaData來(lái)表示Table對(duì)象的集合。這種結(jié)構(gòu)來(lái)源于Martin Fowler的描述大多來(lái)自“元數(shù)據(jù)映射”企業(yè)應(yīng)用架構(gòu)模式 。圖20.5所示一些關(guān)鍵要素的sqlalchemy.schema包。 圖20.5:基本sqlalchem??y.schema的對(duì)象
Table代表一個(gè)實(shí)際的表的名稱和其他屬性目前在目標(biāo)模式。它的Column對(duì)象的集合代表命名并鍵入有關(guān)單個(gè)表列的信息。一個(gè)完整的數(shù)組對(duì)象的描述約束,索引和序列設(shè)置,以填補(bǔ)在有更多的細(xì)節(jié),其中一些影響的引擎和SQL施工系統(tǒng)行為。特別是, ForeignKeyConstraint 是中央確定兩個(gè)表中應(yīng)加入。
架構(gòu)中的包Column Table和Column相對(duì)于其余的是唯一的包,因?yàn)樗鼈兪请p繼承,無(wú)論從sqlalchemy.schema包,sqlalchemy.sql.expression包,服務(wù)不只是為模式水平結(jié)構(gòu),但也可作為核心的SQL表達(dá)式語(yǔ)言的語(yǔ)法單位。圖20.6中示出這種關(guān)系。 圖20.6:表和列的雙重生活
在圖20.6中,我們可以看到, Table和Column繼承的SQL世界具體形式“的東西,你可以選擇”,被稱為一個(gè)FromClause ,和“東西,你可以使用SQL表達(dá)式”,被稱為一個(gè)ColumnElement 。 20.5SQL表達(dá)式
在SQLAlchem??y的創(chuàng)作中,SQL生成的方法是不明確的。文本語(yǔ)言可能是一個(gè)可能的候選人,這是一種常見(jiàn)的方法是在知名的核心對(duì)象 - 關(guān)系的工具像Hibernate的HQL。然而,對(duì)于Python,更有趣的選擇是:使用Python對(duì)象和表達(dá)式generatively建設(shè)的表達(dá)式目錄樹(shù)結(jié)構(gòu),甚至利用Python的運(yùn)營(yíng)商,所以運(yùn)營(yíng)商可以給定的SQL語(yǔ)句行為。
雖然它可能不會(huì)一直是這樣做的第一個(gè)工具,全歸功于在伊恩的SQLBuilder庫(kù)Bicking SQLObject來(lái)的靈感系統(tǒng)的使用Python對(duì)象和運(yùn)營(yíng)商SQLAlchem??y的表達(dá)語(yǔ)言。在這種方法中,Python對(duì)象代表一個(gè)SQL的詞匯部分表達(dá)。在這些對(duì)象上的方法,以及重載運(yùn)算符,產(chǎn)生新的詞匯結(jié)構(gòu)來(lái)源于它們。最常見(jiàn)的目的是“列”將代表這些對(duì)象SQLObject的一個(gè)ORM映射類.q屬性可以通過(guò)使用一個(gè)命名空間;SQLAlchemy的命名屬性.c 。的.c 屬性今天仍然是核心的可選元素,如表和select語(yǔ)句。 表達(dá)式樹(shù)
一個(gè)SQLAlchem??y的SQL表達(dá)式結(jié)構(gòu),這種結(jié)構(gòu)是非常你,如果你想創(chuàng)建解析SQL語(yǔ)句,它是一個(gè)解析樹(shù),除了開(kāi)發(fā)人員創(chuàng)建的解析樹(shù)直接,而不是它從一個(gè)字符串導(dǎo)出。的核心類型的節(jié)點(diǎn),在該解析樹(shù)被稱為的ClauseElement , 圖20.7示出的關(guān)系ClauseElement一些關(guān)鍵類。 圖20.7:基本表達(dá)層次
通過(guò)使用構(gòu)造函數(shù),方法和重載的Python操作功能,這樣的語(yǔ)句結(jié)構(gòu)為:
SELECT ID FROM用戶,其中name =?
可能建造在Python中,如:
從導(dǎo)入表中sqlalchem??y.sql,列中,選擇用戶表('用戶'('身份證'),列,列(“名稱”))到stmt =選擇(user.c.id])。(user.c.name =='編輯')
在select 圖20.8中示出的結(jié)構(gòu)的上述select構(gòu)造。注意:表示包含的文本值'ed'內(nèi)_BindParam構(gòu)造,從而導(dǎo)致它被呈現(xiàn)為綁定參數(shù)標(biāo)記的SQL字符串使用一個(gè)問(wèn)號(hào)。 圖20.8:例表達(dá)式樹(shù)
從樹(shù)形圖中,人們可以看到,通過(guò)一個(gè)簡(jiǎn)單的降穿越節(jié)點(diǎn)可以快速創(chuàng)建一個(gè)呈現(xiàn)的SQL語(yǔ)句,我們會(huì)看到更細(xì)節(jié)一節(jié)中的語(yǔ)句編譯。 Python的操作方法
在SQLAlchem??y,這樣的表達(dá)式:
列('A')== 2
生產(chǎn)既不True也不False ,而是一個(gè)SQL表達(dá)式興建。 關(guān)鍵是使用Python特殊的重載操作符操作員功能:例如,方法如eq?,?ne?,le?,?lt?,?add?,?mul?。面向列表達(dá)式節(jié)點(diǎn)提供重載通過(guò)使用Python的操作人員的行為一個(gè)mixin ColumnOperators 。使用操作符重載,一個(gè)表達(dá)column('a') == 2等價(jià)于:
從sqlalchem??y.sql.expression進(jìn)口_BinaryExpression從進(jìn)口柱sqlalchem??y.sql,bindparam,距離sqlalchem??y.operators進(jìn)口EQ _BinaryExpression(左=('a')的列中,右= bindparam('A',值= 2,獨(dú)特的= TRUE),=操作符式)
eq結(jié)構(gòu)實(shí)際上是一個(gè)函數(shù)從Python的內(nèi)置的operator 。代表運(yùn)營(yíng)商作為一個(gè)對(duì)象(例如,operator.eq ),而不是一個(gè)字符串(即, = )允許字符串表示定義在語(yǔ)句的編譯時(shí)間,當(dāng)數(shù)據(jù)庫(kù)方言信息是已知的。 精選集
負(fù)責(zé)渲染成文本的SQL表達(dá)式樹(shù)的中央級(jí)SQL是Compiled類。這個(gè)類有兩個(gè)主要的子類, SQLCompilerDDLCompiler 。SQLCompiler處理SQL的渲染操作為SELECT,INSERT,UPDATE和DELETE語(yǔ)句,統(tǒng)稱為數(shù)據(jù)查詢語(yǔ)言(DQL)DML(數(shù)據(jù)操縱語(yǔ)言),而DDLCompiler處理各種CREATE和列為DROP語(yǔ)句,數(shù)據(jù)定義語(yǔ)言(DDL)。有一個(gè)額外的類層次結(jié)構(gòu),重點(diǎn)圍繞字符串表示形式的類型,開(kāi)始在TypeCompiler 。個(gè)人方言然后提供自己的所有三個(gè)編譯器類型的子類定義特定的目標(biāo)數(shù)據(jù)庫(kù)的SQL語(yǔ)言方面。圖20.9提供了一個(gè)相對(duì)于這個(gè)類層次的概述PostgreSQL的話。 圖20.9:編譯器的層次結(jié)構(gòu),包括PostgreSQL的具體實(shí)施
Compiled的子類定義了一系列的訪問(wèn)方法,每個(gè)一提到一個(gè)特定的子類的ClauseElement 。層次結(jié)構(gòu)ClauseElement節(jié)點(diǎn)的一份聲明中行走,是通過(guò)每次訪問(wèn)函數(shù)的遞歸連接的字符串輸出。由于這個(gè)收益, Compiled對(duì)象維護(hù)國(guó)家有關(guān)匿名標(biāo)識(shí)符名稱,綁定參數(shù)名稱,嵌套子查詢,除其他事項(xiàng)外,所有的生產(chǎn)的SQL語(yǔ)句的字符串,以及作為最終目的收集綁定的參數(shù)使用默認(rèn)值。圖20.10說(shuō)明訪問(wèn)方法的過(guò)程中,在文本單元。 圖20.10:呼叫層次的語(yǔ)句編譯
一個(gè)完成的Compiled結(jié)構(gòu)包含完整的SQL字符串,并綁定值的集合。這些都是強(qiáng)制的ExecutionContext到DBAPI的execute預(yù)期的格式 方法,其中包括這樣的考慮,治療的Unicode語(yǔ)句對(duì)象的集合類型使用存儲(chǔ)綁定值,以及具體如何綁定值自己應(yīng)該被強(qiáng)迫交涉適當(dāng)?shù)腄BAPI目標(biāo)數(shù)據(jù)庫(kù)。 20.6類映射的ORM
現(xiàn)在我們的注意力轉(zhuǎn)移到ORM。第一個(gè)目標(biāo)是使用系統(tǒng)表的元數(shù)據(jù)中,我們定義了允許一個(gè)用戶定義的類映射到數(shù)據(jù)庫(kù)表中的列的集合。第二個(gè)目標(biāo)是讓用戶定義的類之間的關(guān)系的定義,根據(jù)數(shù)據(jù)庫(kù)中的表之間的關(guān)系。
SQLAlchem??y的“映射”,是指這眾所周知的數(shù)據(jù)映射器模式描述在福勒的企業(yè)架構(gòu)模式 ??傮w而言,SQLAlchem??y的ORM大量借鑒由福勒的做法詳細(xì)介紹。它也嚴(yán)重影響了著名的Java關(guān)系映射工具Hibernate和伊恩Bicking為Python的SQLObject的產(chǎn)品。 古典與聲明
我們使用的術(shù)語(yǔ)古典映射到參考SQLAlchemy的系統(tǒng)的應(yīng)用對(duì)象 - 關(guān)系數(shù)據(jù)映射到一個(gè)現(xiàn)有的用戶類。這形式參考Table對(duì)象和用戶定義的類有兩個(gè)單獨(dú)定義的實(shí)體連接在一起,通過(guò)一個(gè)函數(shù)調(diào)用對(duì)映表,一旦mapper已應(yīng)用到一個(gè)用戶定義的類,類需要新的屬性對(duì)應(yīng)表中的列:
類用戶(對(duì)象):通過(guò) 映射(用戶user_table) ?,F(xiàn)在用戶有一個(gè)“id”屬性用戶名
mapper也可以貼上其他各種屬性的類,包括屬性對(duì)應(yīng)于其他種對(duì)象的引用,以及為任意的SQL表達(dá)式。粘貼任意屬性的過(guò)程中一類是被稱為在Python世界為“的monkeypatching”的,但由于我們是在數(shù)據(jù)驅(qū)動(dòng)的和非任意的方式,這樣做的精神,操作的更好地表達(dá)這個(gè)術(shù)語(yǔ)類儀器儀表 。
現(xiàn)代使用的SQLAlchem??y的中心,周圍的聲明的擴(kuò)展,這是一種可配置的系統(tǒng),類似于共同有效記錄系統(tǒng)所使用的許多其他類的聲明對(duì)象 - 關(guān)系的工具。在這個(gè)系統(tǒng)中,最終用戶明確定義屬性內(nèi)聯(lián)類的定義,每個(gè)代表一個(gè)屬性類,它是要被映射的。Table對(duì)象,在大多數(shù)情況下,是不明確提到,也不是mapper功能,只有類,Column對(duì)象,與其他ORM相關(guān)的屬性被命名為:
類用戶(基本):tablename?='用戶'ID =列(如Integer,primary_key的= TRUE)
它可能會(huì)出現(xiàn),上面的類儀器直接實(shí)現(xiàn)由我們的放置id = Column()但這種情況并非如此。的聲明擴(kuò)展使用Python元類,這是一個(gè)方便的方法來(lái)執(zhí)行一系列的操作,每次一個(gè)新的類首先聲明,生成一個(gè)新的Table 從什么被宣布的對(duì)象,并通過(guò)它的mapper功能,隨著類。mapper功能,然后在完全相同的方式,它的工作修補(bǔ)它自己的屬性類上,在這種情況下向id屬性,和更換有以前。元類初始化的時(shí)候是完整的(也就是,當(dāng)執(zhí)行的流程離開(kāi)由User劃定的塊),標(biāo)記的id Table User.id Column對(duì)象被移動(dòng)到一個(gè)新的Table , User.id 已被替換特定映射由一個(gè)新的屬性。
它總是SQLAlchem??y的將有一個(gè)的簡(jiǎn)寫,聲明的形式配置。然而,創(chuàng)造的聲??明延遲贊成繼續(xù)工作,鞏固了力學(xué)的經(jīng)典測(cè)繪的。中期的擴(kuò)展名為ActiveMapper,這后來(lái)成為藥劑項(xiàng)目,早在存在。它重新定義映射構(gòu)造在一個(gè)更高的級(jí)別申報(bào)制度。聲明的目標(biāo)是扭轉(zhuǎn)藥劑的大量抽象的方向通過(guò)建立一個(gè)系統(tǒng)的方法保留SQLAlchem??y的經(jīng)典地圖繪制概念,幾乎確切地說(shuō),只有重組它們是如何使用不再繁瑣,更適合類級(jí)別的擴(kuò)展比經(jīng)典的映射。
無(wú)論是古典或聲明的映射,映射的類需要新的行為,允許它來(lái)表達(dá)其屬性中的SQL結(jié)構(gòu)。SQLAlchem??y的最初跟著SQLObject的使用一個(gè)特殊的行為通過(guò)SQLAlchem??y的屬性為SQL列表達(dá)式的來(lái)源,提到.c ,在這個(gè)例子中:
結(jié)果= session.query(用戶)。過(guò)濾器(User.c.username =='編輯')。所有的()
然而,在0.4版本中,SQLAlchem??y的移動(dòng)到映射的功能屬性本身:
結(jié)果= session.query(用戶)。過(guò)濾器(User.username =='編輯')。所有的()
在屬性的訪問(wèn)證明了這種變化有很大的改進(jìn),因?yàn)樗鼘櫸锏牧袪畹奈矬w目前的類,以獲得額外的類特定的功能目前來(lái)自直接從底層Table對(duì)象。很顯然,那位同事是位多產(chǎn)教案,列表名單很大,所以教師選擇更先進(jìn)的搜索,并增加了也允許使用不同的類屬性之間的整合,如直接指到表列的屬性,屬性,來(lái)自這些列的SQL表達(dá)式和屬性,請(qǐng)參閱相關(guān)的類。最后,它提供了一個(gè)對(duì)稱之間的映射類,同樣的屬性,以及該映射的類的實(shí)例,可以采取不同的行為取決于類型的父。綁定類屬性返回SQL表達(dá)式,同時(shí)結(jié)合實(shí)例屬性返回實(shí)際的數(shù)據(jù)。 映射的剖析
一直連接到我們的id User類的id屬性,是一種在Python中的對(duì)象,對(duì)象為一個(gè)描述符有get?,?set,和del方法,它的Python運(yùn)行時(shí)按照所有涉及該屬性的類和實(shí)例操作。SQLAlchemy的實(shí)施稱為一個(gè)InstrumentedAttribute ,我們將舉例說(shuō)明背后所呈現(xiàn)的世界與另一個(gè)例子。從一個(gè)Table和一個(gè)用戶定義的類,我們建立了一個(gè)映射只有一個(gè)映射列relationship ,以及相關(guān)的類,它定義了一個(gè)參考:
user_table表(“用戶”,元數(shù)據(jù),列('身份證',整數(shù),primary_key的= TRUE),) 類用戶(對(duì)象):通過(guò) 映射器(用戶,user_table,屬性= {“相關(guān)”的關(guān)系(地址)})
當(dāng)映射的結(jié)構(gòu)是完整的,有關(guān)的類的對(duì)象的詳細(xì)的圖20.11中。 圖20.11:映射的剖析
該圖說(shuō)明了SQLAlchem??y的映射定義為兩個(gè)獨(dú)立的層用戶定義的類和表的元數(shù)據(jù)之間的互動(dòng),它被映射。圖向左類儀器儀表,而SQL和數(shù)據(jù)庫(kù)功能是朝著正確的合照。一般模式玩的是對(duì)象的組合是用來(lái)隔離行為的角色和對(duì)象繼承用來(lái)區(qū)分在一個(gè)特定的角色之間的行為差??異。
類儀器儀表領(lǐng)域內(nèi), ClassManager被映射的類,而其收集的InstrumentedAttribute對(duì)象是與每個(gè)屬性映射的類。InstrumentedAttribute是面向公眾的Python的描述符前面提到的,產(chǎn)生SQL表達(dá)式時(shí),使用基于類的表達(dá)式(例如, User.id==5 )。.在...時(shí)候, 何時(shí)處理的一個(gè)實(shí)例User , InstrumentedAttribute代表的行為歸因于AttributeImpl對(duì)象,這是一個(gè)專門對(duì)幾個(gè)品種所表示的數(shù)據(jù)類型。
建立的映射側(cè), Mapper代表一個(gè)用戶定義的類和一個(gè)可選擇的單元的聯(lián)動(dòng),最典型的Table 。Mapper維護(hù)一組每個(gè)屬性的對(duì)象,被稱為為MapperProperty ,其中涉及的SQL表示的特定屬性。最常見(jiàn)的變種MapperProperty ColumnProperty ,一個(gè)映射的字段或SQL表達(dá)式,并RelationshipProperty ,代表一個(gè)連接到另一個(gè)映射。
MapperProperty代表屬性裝載行為,包括屬性如何呈現(xiàn)在一個(gè)SQL語(yǔ)句,以及如何從結(jié)果來(lái)填充行一個(gè)LoaderStrategy對(duì)象,其中有幾個(gè)品種。不同LoaderStrategies確定的裝載行為,屬性被延遲 , 躍躍欲試 ,或直接 。選擇默認(rèn)的版本映射配置時(shí)間,在查詢時(shí)可以選擇使用一個(gè)備用的策略。RelationshipProperty也的引用了DependencyProcessor ,處理,如何映射器間的依賴關(guān)系和屬性同步進(jìn)行沖洗時(shí)間。父和目標(biāo)的關(guān)系幾何形狀的基礎(chǔ)上選擇DependencyProcessor selectables鏈接關(guān)系。
的的Mapper / RelationshipProperty結(jié)構(gòu)形成一個(gè)圖,其中Mapper對(duì)象的節(jié)點(diǎn)RelationshipProperty對(duì)象的有向邊。一旦全套映射器已被宣布由一個(gè)應(yīng)用程序,遞延“初始化”步驟被稱為組態(tài)前進(jìn)。它主要用于每個(gè)RelationshipProperty ,以鞏固其母公司和細(xì)節(jié)之處的目標(biāo)映射器,包括選擇的AttributeImpl以及作為DependencyProcessor 。此圖是一個(gè)關(guān)鍵的數(shù)據(jù)結(jié)構(gòu),用于整個(gè)操作過(guò)程中的ORM。它參與操作,如所謂的“級(jí)聯(lián)”的行為,定義了如何操作應(yīng)該傳播沿著對(duì)象的路徑,查詢操作相關(guān)的對(duì)象和集合“眼巴巴”加載一次,以及對(duì)對(duì)象沖洗側(cè)一個(gè)之前建立的所有對(duì)象引發(fā)了一系列的依賴圖持久性的步驟。 20 / 7查詢和裝載行為
SQLAlchemy的啟動(dòng)通過(guò)一個(gè)對(duì)象調(diào)用Query所有對(duì)象的裝載行為?;A(chǔ)狀態(tài)Query開(kāi)始,包括實(shí)體 ,這是映射類列表和/或獨(dú)立的SQL表達(dá)式進(jìn)行查詢。它也有一個(gè)參考Session ,它表示連接到一個(gè)或多個(gè)數(shù)據(jù)庫(kù),以及一個(gè)高速緩存的數(shù)據(jù)的相對(duì)于累計(jì)這些連接上的交易。下面是一個(gè)基本的用法示例:
從sqlalchem??y.orm導(dǎo)入Session屆會(huì)議(發(fā)動(dòng)機(jī))查詢session.query(用戶)
我們創(chuàng)建了一個(gè)Query ,將產(chǎn)生的User情況下,相對(duì)于一個(gè)新的Session ,我們已經(jīng)創(chuàng)建。在同一Query提供了一個(gè)生成生成器模式select結(jié)構(gòu)的方式前面所討論的,額外的標(biāo)準(zhǔn)和修飾符與在一份聲明中構(gòu)造一個(gè)方法調(diào)用的時(shí)間。當(dāng)一個(gè)迭代運(yùn)算被稱為上的Query ,它構(gòu)造一個(gè)SQL表達(dá)式構(gòu)造代表一個(gè)SELECT,把它發(fā)射到數(shù)據(jù)庫(kù)中,然后解釋的結(jié)果集行面向ORM的結(jié)果對(duì)應(yīng)于所請(qǐng)求的實(shí)體的初始集合。
Query進(jìn)行硬的SQL渲染的區(qū)別 和數(shù)據(jù)加載的操作的部分。前者是指建設(shè)一個(gè)SELECT語(yǔ)句,后者的解釋SQL結(jié)果行ORM映射的構(gòu)造。數(shù)據(jù)加載,其實(shí),繼續(xù)進(jìn)行沒(méi)有一個(gè)SQL呈現(xiàn)步驟,的Query可能會(huì)被要求解釋結(jié)果一個(gè)文本查詢手由用戶組成。
這兩個(gè)SQL渲染和數(shù)據(jù)加載利用遞歸下降形成的曲線圖由一系列鉛Mapper對(duì)象,考慮每一列或SQL表達(dá)式控股ColumnProperty作為一個(gè)葉子結(jié)點(diǎn),每個(gè)這是通過(guò)所謂的“急切負(fù)荷”要包含在查詢中的RelationshipProperty作為一個(gè)邊緣到另一個(gè)Mapper節(jié)點(diǎn)。遍歷和要采取的行動(dòng),在每個(gè)節(jié)點(diǎn)最終是每個(gè)LoaderStrategy與每MapperProperty相關(guān)工作,添加列,并加入到正在興建的SELECT語(yǔ)句在SQL呈現(xiàn)階段,Python函數(shù)來(lái)處理結(jié)果行中的數(shù)據(jù)加載階段。
Python函數(shù)中的數(shù)據(jù)加載階段,每個(gè)接收數(shù)據(jù)庫(kù)中的一行,因?yàn)樗鼈兪菭繌?qiáng),產(chǎn)生的狀態(tài)可能有變?cè)诖鎯?chǔ)器中的映射的屬性作為一個(gè)結(jié)果。它們產(chǎn)生的一個(gè)特定的屬性有條件的,根據(jù)檢查結(jié)果集的第一個(gè)入行,以及加載選項(xiàng)。如果負(fù)載的屬性是不繼續(xù)進(jìn)行,沒(méi)有可調(diào)用的函數(shù)。
圖20.12說(shuō)明了遍歷幾個(gè)LoaderStrategy對(duì)象中加入的渴望加載 情況下,說(shuō)明其提供的SQL語(yǔ)句的連接過(guò)程中發(fā)生的_compile_context 方法Query 。這也表明新一代的的行人口的功能,收到的結(jié)果行和填充單個(gè)對(duì)象的屬性,這個(gè)過(guò)程發(fā)生在instances的Query方法。 圖20.12:穿越的裝載機(jī)的戰(zhàn)略,包括一個(gè)加入預(yù)先加載
SQLAlchem??y的早期結(jié)果來(lái)填充方法使用傳統(tǒng)的穿越固定對(duì)象的方法與每一個(gè)收到的每一行的戰(zhàn)略和采取相應(yīng)的行動(dòng)。加載程序可調(diào)用的系統(tǒng),首先在0.5版本中引入的,代表一個(gè)巨大的飛躍,性能,因?yàn)楹芏鄾Q策就行可以了只是一次處理了前面,而不是為每一行,和一個(gè)顯著數(shù)量的函數(shù)調(diào)用沒(méi)有凈影響可能會(huì)被淘汰。 20.8會(huì)議/標(biāo)識(shí)映射
在SQLAlchem??y,Session對(duì)象的實(shí)際使用情況,提出了公共接口ORM的,也就是說(shuō),加載和持久化數(shù)據(jù)。它提供的起始角度為給定的數(shù)據(jù)庫(kù)連接查詢和堅(jiān)持行動(dòng)。
Session ,除了作為數(shù)據(jù)庫(kù)連接的網(wǎng)關(guān),這是目前所有映射實(shí)體的集合保持一個(gè)積極的參考在內(nèi)存中相對(duì)于該Session 。在這樣的Session 的身份地圖和單位的工作模式,既實(shí)現(xiàn)了一個(gè)門面確定由福勒。一個(gè)數(shù)據(jù)庫(kù)唯一的身份標(biāo)識(shí)映射保持映射為一個(gè)特定的Session中的所有對(duì)象,消除了存在的問(wèn)題重復(fù)的身份介紹。工作單位的基礎(chǔ)上的身份地圖提供的持久化狀態(tài)的變化過(guò)程自動(dòng)化系統(tǒng)數(shù)據(jù)庫(kù)中的盡可能最有效的方式。實(shí)際的持久性步驟是被稱為“沖洗”,和在現(xiàn)代的SQLAlchem??y此步驟通常是自動(dòng)的。 發(fā)展歷史
Session開(kāi)始大多隱蔽系統(tǒng)負(fù)責(zé)單散發(fā)出齊平的任務(wù)。沖洗過(guò)程中涉及發(fā)光SQL報(bào)表到數(shù)據(jù)庫(kù)中,對(duì)應(yīng)的對(duì)象的狀態(tài)中的變化跟蹤工作制的單位,從而同步的當(dāng)前狀態(tài)在內(nèi)存中的數(shù)據(jù)庫(kù)。的沖洗一直是一個(gè)最SQLAlchem??y的復(fù)雜的操作。
方法的調(diào)用非常早期版本的同花順開(kāi)始在背后被稱為commit ,這是方法上存在一個(gè)隱式的,線程局部對(duì)象objectstore 。當(dāng)一個(gè)人使用SQLAlchem??y的0.1,因此沒(méi)有必要打電話Session.add ,也沒(méi)有任何一個(gè)明確的概念Session的。唯一的面向用戶的步驟是創(chuàng)建映射器,創(chuàng)建新的對(duì)象,修改現(xiàn)有對(duì)象加載查詢(查詢每個(gè)Mapper對(duì)象直接從自己被調(diào)用),然后堅(jiān)持所有通過(guò)objectstore.commit命令。池中的對(duì)象的一組操作無(wú)條件模塊全局的和無(wú)條件的線程局部。
與第一組objectstore.commit模型是直接命中的用戶,但此模型的剛性很快撞上了墻?,F(xiàn)代SQLAlchem??y的新用戶有時(shí)感嘆,需要定義一個(gè)工廠,可能是注冊(cè)表,Session對(duì)象,以及需要保持自己的對(duì)象組織成只是一個(gè)Session的時(shí)間,但是這是遠(yuǎn)遠(yuǎn)最好的初期,當(dāng)整個(gè)系統(tǒng)完全是隱含的。“0.1使用模式的方便,在很大程度上仍是在現(xiàn)代社會(huì)本SQLAlchem??y的,其特點(diǎn)通常配置為一個(gè)會(huì)話注冊(cè)表使用線程局部范圍。
Session本身只介紹SQLAlchemy的0.2版,建模后在Hibernate Session對(duì)象存在松散。這個(gè)版本的特色綜合事務(wù)控制,其中的Session可以被放置到一個(gè)事務(wù)中通過(guò)begin方法,并完成通過(guò)commit方法。objectstore.commit方法更名為objectstore.flush ,新的Session對(duì)象可以在任何時(shí)間創(chuàng)建。Session本身被打破了從另一個(gè)對(duì)象UnitOfWork ,這仍然是一個(gè)私人反對(duì)負(fù)責(zé)執(zhí)行實(shí)際的刷新操作。
,雖然沖洗過(guò)程中顯式調(diào)用方法用戶,0.4系列的SQLAlchemy的概念引入的自動(dòng)刷新 ,這意味著,刷新每次查詢前立即發(fā)出。它的優(yōu)點(diǎn)自動(dòng)刷新的是,所發(fā)出的SQL語(yǔ)句的查詢總是有關(guān)系側(cè)訪問(wèn)的確切狀態(tài),存在于存儲(chǔ)器中,所有的改變都送了過(guò)來(lái)。早期版本的SQLAlchem??y的不包括此功能,因?yàn)樽畛R?jiàn)的使用模式FLUSH語(yǔ)句也承諾永久性的變化。但是,當(dāng)自動(dòng)刷新?lián)榻B,它是伴隨著另一個(gè)特點(diǎn)所謂的事務(wù)性 Session ,它提供了一個(gè)Session會(huì)自動(dòng)啟動(dòng)的交易中,一直持續(xù)到用戶名為commit明確。此功能的推出, flush方法不再犯,它刷新的數(shù)據(jù),并能安全被稱為一個(gè)自動(dòng)化的基礎(chǔ)上。Session ,而現(xiàn)在,提供了一步一步的同步內(nèi)存中的狀態(tài)和SQL查詢狀態(tài)之間進(jìn)行沖洗根據(jù)需要,什么也沒(méi)有永久持續(xù),直到明確commit第一步。這種行為是,事實(shí)上,在Hibernate中完全相同的Java。然而,SQLAlchem??y的擁抱為Python相同的行為在風(fēng)暴ORM的基礎(chǔ)上,使用這種風(fēng)格的介紹SQLAlchem??y的是在0.3版本的時(shí)候。
0.5版帶來(lái)了更多的交易整合后交易到期推出后,每一個(gè)commit或rollback ,默認(rèn)所有國(guó)家內(nèi)的Session已過(guò)期(清除),來(lái)填充后續(xù)SQL語(yǔ)句時(shí)再重新選擇數(shù)據(jù)時(shí),或當(dāng)在剩余的過(guò)期的對(duì)象的屬性中訪問(wèn)新事務(wù)的上下文中。最初,SQLAlchem??y的周圍建造假設(shè)SELECT語(yǔ)句應(yīng)盡可能少排放,無(wú)條件的。過(guò)期的提交行為是緩慢的,在此原因,但是,它完全解決問(wèn)題的Session載有過(guò)時(shí)的數(shù)據(jù)交易后,沒(méi)有簡(jiǎn)單的方式來(lái)加載新的數(shù)據(jù)沒(méi)有重建的全套已加載的對(duì)象。在早期,它似乎這個(gè)問(wèn)題不能合理解決,因?yàn)樗强床怀鰜?lái)的時(shí)Session應(yīng)考慮目前的狀態(tài)是過(guò)時(shí)的,從而昂貴的新集的SELECT語(yǔ)句在下次訪問(wèn)。但是,一旦Session轉(zhuǎn)移到一個(gè)始終保持在一個(gè)交易模型,交易結(jié)束點(diǎn)變得明顯,自然點(diǎn)的數(shù)據(jù)過(guò)期,作為一個(gè)事務(wù)的性質(zhì)具有高度隔離是, 它不能看到新的數(shù)據(jù),直到它的承諾或回滾了。不同的數(shù)據(jù)庫(kù)和配置,當(dāng)然有不同程度的事務(wù)隔離,包括沒(méi)有在所有的交易。這些模式的使用是完全可以接受的,SQLAlchem??y的到期使用較低的隔離模型,開(kāi)發(fā)人員只需要知道,水平內(nèi)如果有多個(gè)會(huì)話的會(huì)話可能會(huì)使未隔離的變化共享相同的行。這是不是在所有不同,什么都可以發(fā)生時(shí)直接使用兩個(gè)數(shù)據(jù)庫(kù)連接。 會(huì)議概述 圖20.13說(shuō)明了Session的主要結(jié)構(gòu)處理。 圖20.13:會(huì)議概述
面向公眾的部分上面是Session本身和用戶對(duì)象的集合,每一個(gè)映射的類的一個(gè)實(shí)例。在這里,我們看到映射的對(duì)象保持一個(gè)SQLAlchemy的建設(shè)的參考InstanceState ,跟蹤ORM一個(gè)單獨(dú)的實(shí)例包括待處理的屬性的變化和屬性的狀態(tài)過(guò)期狀態(tài)。InstanceState 在前面的討論是實(shí)例級(jí)側(cè)的屬性儀表節(jié), 映射的剖析 ,一流水平的ClassManager相對(duì)應(yīng),并保持狀態(tài)的映射對(duì)象的字典(即Python的dict?代表的AttributeImpl相關(guān)聯(lián)的對(duì)象的類屬性) 。 狀態(tài)跟蹤
IdentityMap是數(shù)據(jù)庫(kù)身份InstanceState對(duì)象的映射,對(duì)于那些有一個(gè)數(shù)據(jù)庫(kù)的身份,這被稱為持久性的對(duì)象。的默認(rèn)實(shí)現(xiàn)IdentityMap與InstanceState自我管理其大小所有強(qiáng)引用刪除用戶映射的情況下,一旦他們已被刪除的它的工作方式以同樣的方式作為Python的WeakValueDictionary 。、 保護(hù)組的所有對(duì)象標(biāo)記為臟或刪除 ,以及有待對(duì)象的標(biāo)新 ,收集垃圾,通過(guò)建立強(qiáng)大的對(duì)這些對(duì)象的引用掛起的更改。所有的強(qiáng)引用,然后被丟棄后沖水。
InstanceState也執(zhí)行的關(guān)鍵任務(wù),保持“有什么變化”對(duì)于一個(gè)特定的對(duì)象的屬性,使用此舉變化系統(tǒng)“先前”的一個(gè)特定的屬性值存儲(chǔ)在字典中稱為committed_state前傳入的值賦給對(duì)象的電流詞典。沖洗時(shí)間,內(nèi)容committed_state 和與該對(duì)象相關(guān)聯(lián)的dict比較,以產(chǎn)生組凈變化對(duì)每個(gè)對(duì)象。
在集合的情況下,一個(gè)單獨(dú)的collections包坐標(biāo)與InstrumentedAttribute / InstanceState 系統(tǒng),以保持一個(gè)特定的映射集合的集合變動(dòng)凈額del常見(jiàn)的Python類,如set , list和dict的子類在使用前和增強(qiáng)與歷史跟蹤mutator方法。收集系統(tǒng)在0.4?是開(kāi)放式的,可用于任何集合類對(duì)象進(jìn)行了修改。 事務(wù)控制
Session ,在默認(rèn)狀態(tài)下的使用,維護(hù)打開(kāi)事務(wù)的所有操作完成時(shí)commit或rollback被稱為?!癝essionTransaction維護(hù)一組零個(gè)或多個(gè)Connection對(duì)象,每個(gè)對(duì)象代表一個(gè)開(kāi)放的交易在一個(gè)特定的數(shù)據(jù)庫(kù)。SessionTransaction是一個(gè)懶惰的初始化的對(duì)象,開(kāi)始沒(méi)有數(shù)據(jù)庫(kù)的狀態(tài)存在。作為一個(gè)特殊的后端需要參加在一份聲明中執(zhí)行, Connection對(duì)應(yīng)于該數(shù)據(jù)庫(kù)添加到SessionTransaction的名單連接安全要求.雖然在一個(gè)時(shí)間是一個(gè)單一的連接常見(jiàn)的,支持多種連接方案在特定的連接,用于一個(gè)特定的操作基于配置與Table , Mapper或SQL構(gòu)建自己參與運(yùn)作。多重連接也可以使用協(xié)調(diào)事務(wù)兩相的的行為,它提供那些DBAPIs。 20.9工作單位
提供flush Session將在其工作的flush方法一個(gè)獨(dú)立的模塊unitofwork 。正如前面提到的,沖洗過(guò)程可能是SQLAlchem??y的最復(fù)雜的功能。
工作單位的工作是將所有的掛起狀態(tài),目前在一個(gè)特定的Session到數(shù)據(jù)庫(kù)中,掏空了new , dirty ,和deleted 收藏保持的Session 。完成后,內(nèi)存中的狀態(tài)Session的,什么是在當(dāng)前事務(wù)中的比賽。面臨的主要挑戰(zhàn)是確定正確的一系列的持久性的步驟,然后按正確的順序來(lái)執(zhí)行它們。這包括確定INSERT,UPDATE和DELETE語(yǔ)句的列表,其中包括因從級(jí)聯(lián)的相關(guān)行被刪除或以其他方式移動(dòng),確保UPDATE報(bào)表只包含那些真正被修改的列,建立“同步”操作外鍵引用的主鍵列,將復(fù)制的狀態(tài)列,在該點(diǎn)在該新生成的主密鑰標(biāo)識(shí)符可確保發(fā)生插入的對(duì)象添加到Session的順序盡可能有效,并確保UPDATE和DELETE語(yǔ)句出現(xiàn)在一個(gè)確定順序所以,以減少機(jī)會(huì)死鎖。 歷史
作為一個(gè)糾纏不清的系統(tǒng)結(jié)構(gòu),工作落實(shí)的單位開(kāi)始寫在一個(gè)特設(shè)的方式,它的發(fā)展可以進(jìn)行比較,發(fā)現(xiàn)沒(méi)有出路的森林地圖。早期的錯(cuò)誤和缺少行為解決與螺栓連接修復(fù),而一些重構(gòu),改善的事項(xiàng)通過(guò)0.5版本,它直到0.6版本,工作單位,時(shí)間穩(wěn)定,很好理解,所涵蓋的上百個(gè)測(cè)試完全從頭開(kāi)始重寫。經(jīng)過(guò)幾個(gè)星期的考慮一個(gè)新的的方法,將驅(qū)動(dòng)由一致的數(shù)據(jù)結(jié)構(gòu),過(guò)程重寫它使用這個(gè)新的模型只用了幾天,當(dāng)時(shí)的想法是這個(gè)時(shí)候,充分的了解。它也是的事實(shí),極大地促進(jìn)了新實(shí)施??的行為可能是仔細(xì)對(duì)現(xiàn)有版本進(jìn)行交叉檢查。此過(guò)程顯示如何在第一次迭代的東西,但是可怕的,仍然是有價(jià)值的,因?yàn)橹灰峁┝艘粋€(gè)工作模型。這進(jìn)一步顯示了總的一個(gè)子系統(tǒng)重寫往往是不僅是適當(dāng)?shù)?,但一個(gè)不可分割的一部分的發(fā)展難以開(kāi)發(fā)的系統(tǒng)。 拓?fù)渑判?/p>
后面的工作單元的主要范式是組裝的完整列表,要采取的行動(dòng)到一個(gè)數(shù)據(jù)結(jié)構(gòu)中,每個(gè)節(jié)點(diǎn)代表一個(gè)單一的步驟;在設(shè)計(jì)模式中的說(shuō)法,這被稱為命令模式 。的一系列在該結(jié)構(gòu)中的“命令”,然后組織成一個(gè)特定的順序使用拓?fù)渑判?。拓?fù)渑判蚴且粋€(gè)過(guò)程,一個(gè)偏序 ,各種項(xiàng)目的基礎(chǔ)上,也就是說(shuō),只有某些元素必須先于其他人。圖20.14說(shuō)明了拓?fù)渑判虻男袨椤?圖20.14:拓?fù)渑判?/p>
工作單位構(gòu)建了一個(gè)偏序,那些持久的命令,必須先別人的基礎(chǔ)上?!懊?,然后拓?fù)渑判?,以便調(diào)用。確定哪些命令之前,主要來(lái)自存在的relationship ,填補(bǔ)了兩個(gè)Mapper對(duì)象一般, Mapper 被認(rèn)為是依賴于其他,作為relationship意味著一個(gè)Mapper 有一個(gè)外鍵依賴于其他。類似的規(guī)則存在許多to-many關(guān)聯(lián)表,但在這里,我們專注于的情況下,one-to-many/many-to-one關(guān)系。外鍵的依賴性問(wèn)題解決為了防止發(fā)生,沒(méi)有依賴于無(wú)需違反約束標(biāo)記作為“遞延”的約束。但同樣重要的是,排序允許主鍵標(biāo)識(shí)符,這在許多平臺(tái)上時(shí),只產(chǎn)生一個(gè)INSERT其實(shí)時(shí),被公正執(zhí)行INSERT語(yǔ)句的結(jié)果填充到參數(shù)依賴的行是關(guān)于要插入列表。刪除,使用相同的順序在反向相關(guān)的行之前被刪除那些他們賴以生存,這些行所指的外鍵是不存在的,沒(méi)有演示文稿
工作單位提供系統(tǒng)拓?fù)渑判蛟趦蓚€(gè)不同的級(jí)別,進(jìn)行依賴關(guān)系的結(jié)構(gòu)的基礎(chǔ)上演示文稿第一個(gè)層次,持久性的步驟組織成桶的基礎(chǔ)上之間的依賴關(guān)系的映射器,即,完整的“桶”的對(duì)象對(duì)應(yīng)某個(gè)特定的類。第二電平打破了零個(gè)或多個(gè)這些“桶”成較小的批次,處理的情況下,參考周期或自參照表。如圖20.15所示的“桶”產(chǎn)生的插入的一組User的對(duì)象,那么一組Address的對(duì)象,其中一個(gè)中間步驟,復(fù)制新生成的主鍵的值到User每個(gè)Address對(duì)象的user_id外鍵列。 圖20.15:組織對(duì)象的映射
在每個(gè)映射分揀情況,任何數(shù)目的User和Address對(duì)象可以被刷新沒(méi)有任何影響的復(fù)雜的步驟或多少“依賴關(guān)系”必須考慮的。
排序第二個(gè)層次的組織之間的直接依賴關(guān)系的基礎(chǔ)上的持久性步驟在一個(gè)單一的映射器的范圍之內(nèi)的單個(gè)對(duì)象。當(dāng)發(fā)生這種情況時(shí),最簡(jiǎn)單的例子是一個(gè)表,其中包含一個(gè)外鍵約束本身??需要一個(gè)特定的表中的行前插入另一行同一表中的,是指它的。另一是一系列的表格時(shí)有一個(gè)參考周期 :A引用了表B表,它引用表C,然后參考表A.在別人面前,一些A的對(duì)象必須插入允許的B和C的對(duì)象,也可以插入。表,該表是指本身是一種特殊的情況下,參考周期。
要確定哪些業(yè)務(wù)可以保持在其合并的,每個(gè)Mapper桶,將被分解成一個(gè)更大的集合的每個(gè)對(duì)象的命令,一個(gè)周期檢測(cè)算法被施加到映射器之間存在的依賴關(guān)系的設(shè)定,使用一個(gè)修改的版本的一個(gè)周期Guido van Rossum的博客上發(fā)現(xiàn)的檢測(cè)算法。這些桶在周期是然后再破碎成每個(gè)對(duì)象的操作和通過(guò)混入的集合的每個(gè)映射器水桶此外,每個(gè)對(duì)象桶的新的依賴規(guī)則每映射桶。如圖20.16所示桶中的User對(duì)象被分解成單個(gè)每個(gè)對(duì)象的命令,此外,從relationship User到一個(gè)新的contact relationship本身稱為contact造成的。 圖20.16:組織各個(gè)步驟的參考周期
鏟斗結(jié)構(gòu)背后的基本原理是,它允許共同的批處理報(bào)表盡可能地,既減少所需的步數(shù)Python和實(shí)現(xiàn)更有效的互動(dòng)與DBAPI,有時(shí)可以執(zhí)行一個(gè)Python的報(bào)表內(nèi)方法調(diào)用。只有當(dāng)一個(gè)參考周期之間存在著映射器每個(gè)對(duì)象的依賴模式更昂貴的踢,即使如此,它只發(fā)生對(duì)象圖需要它的那些部分。 {0}·{/0}{1} {/1}{2}20 10{/2}總結(jié)
SQLAlchem??y的目的是非常高的的目標(biāo)是自成立以來(lái),最豐富的功能和靈活的數(shù)據(jù)庫(kù)產(chǎn)品。它已完成因此,雖然維持其專注于關(guān)系型數(shù)據(jù)庫(kù),認(rèn)識(shí)到在深入和全面的方式支持關(guān)系型數(shù)據(jù)庫(kù)的用處是一大創(chuàng)舉,即使是現(xiàn)在,范圍的承諾繼續(xù)顯露自己比以前認(rèn)為的大。
的基于組件的方法的目的是提取每個(gè)區(qū)域的最可能值從的功能,提供了許多不同的單位,應(yīng)用程序可以單獨(dú)使用或組合使用。該系統(tǒng)已具有挑戰(zhàn)性的創(chuàng)建,維護(hù),和交付。
發(fā)展課程的目的是緩慢的基礎(chǔ)上,理論,堅(jiān)實(shí)的功能是有條不紊的,基礎(chǔ)廣泛的建設(shè),最終更有價(jià)值比快速傳遞功能,而無(wú)需基礎(chǔ)。它采取了很長(zhǎng)一段時(shí)間的SQLAlchem??y興建。 一個(gè)一致的,記錄用戶的故事,但在整個(gè)過(guò)程中,底層構(gòu)架始終領(lǐng)先一步,在某些情況下,“時(shí)間機(jī)器”的效果功能,可幾乎在添加用戶要求他們。
Python語(yǔ)言一直是一個(gè)可靠的主機(jī)(如果有點(diǎn)挑剔的,特別是在該地區(qū)的性能)。語(yǔ)言的SQLAlchem??y的一致性,極大地開(kāi)放運(yùn)行模式允許提供一個(gè)更好的比其他語(yǔ)言編寫的同類產(chǎn)品所提供的經(jīng)驗(yàn)。
這是希望的SQLAlchem??y的項(xiàng)目,Python的收益不斷更深的接納到盡可能廣泛的各種各樣的盡可能的領(lǐng)域和行業(yè),使用關(guān)系型數(shù)據(jù)庫(kù)仍然充滿活力和進(jìn)步的。這么做的目標(biāo)是?SQLAlchem??y是表明,關(guān)系型數(shù)據(jù)庫(kù),Python中,考慮的對(duì)象模型都是非常有價(jià)值的開(kāi)發(fā)工具。
更多建議: