- iBATIS框架源碼剖析
- 任鋼
- 6079字
- 2018-12-30 14:35:58
1.2 ORM模型介紹
當Java作為一門語言出現(xiàn)時,一個比較重要的工作任務就是要操作數(shù)據(jù)庫。這就不可避免地要涉及數(shù)據(jù)庫的接口。Sun公司從1996年就把JDBC加入了Java平臺的1.1版本之中,將其作為RDBMS資源管理和數(shù)據(jù)訪問的標準低級抽象層。但是,直接使用JDBC API是相當麻煩的,并且開發(fā)的效率也比較低。這樣,Java ORM模型就橫空出世了。
1.2.1 什么是ORM
O/R Mapping全稱Object Relation Mapping,即對象關(guān)系映射,把對數(shù)據(jù)表映射為對象類,將在數(shù)據(jù)庫中直接進行的原始操作演變?yōu)閷︻惖膶傩院头椒ǖ牟僮鳎g接更改數(shù)據(jù)表的數(shù)據(jù)。
通常,實現(xiàn)ORM框架一般包括以下四部分:
① 對映射類進行CRUD(新增、查詢、修改和刪除)操作的API;
② 規(guī)定Object與Relational之間的映射規(guī)則,一般采用metadata進行表示;
③ 規(guī)定類和類屬性相關(guān)的查詢規(guī)則;
④ 實現(xiàn)ORM中對數(shù)據(jù)庫操作的事務管理。
實現(xiàn)ORM框架也有很多其他的擴展功能,包括緩存處理、分布式事務管理、多種數(shù)據(jù)庫之間的無縫遷徙等等。
1.2.2 ORM的實現(xiàn)方式
關(guān)系數(shù)據(jù)模型則基于數(shù)學原理,特別是集合論的原理,這些原理都能在數(shù)學理論上得到完全的證明。而對象模型基于程序設計的一些原則,類同于一種解決問題的工具,并沒有得到公理或數(shù)學理論的支持。面向?qū)ο笤O計的目標是通過把一個業(yè)務過程分解成具有狀態(tài)和行為的對象來進行建模的業(yè)務過程,而關(guān)系數(shù)據(jù)庫的設計目標是規(guī)范化數(shù)據(jù)以消除數(shù)據(jù)冗余度。兩種不同的理論基礎(chǔ)導致對象模型與關(guān)系數(shù)據(jù)模型之間的阻抗不匹配。面向?qū)ο竽P秃完P(guān)系數(shù)據(jù)模型的阻抗不匹配使得進行對象關(guān)系映射時存在著許多問題。關(guān)系數(shù)據(jù)庫不支持諸如類、繼承、封裝和多態(tài)等面向?qū)ο蟮母拍睢ο箨P(guān)系映射是在對象與數(shù)據(jù)庫之間進行映射的一種技術(shù),對象間的關(guān)系、類及其屬性必須以某種方式映射為關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)庫關(guān)系、表和字段。
針對對象模型與關(guān)系數(shù)據(jù)模型間的阻抗不匹配,人們提出了一些解決方案來實現(xiàn)對象模型向關(guān)系數(shù)據(jù)庫模型的映射,由于數(shù)據(jù)庫是以二維表為基本管理單元的,所以在使用關(guān)系數(shù)據(jù)庫的面向?qū)ο筌浖弥袑ο竽P妥罱K是由二維表以及表間關(guān)系來描述的,而這其實就是一個類與數(shù)據(jù)庫表的變換過程。從某些方面看來,在對象與關(guān)系數(shù)據(jù)庫表的行之間有著很多共同點。對象是類的實例,它的內(nèi)部數(shù)據(jù)的結(jié)構(gòu)以及其他一些特征由某個類定義。類似地,關(guān)系數(shù)據(jù)庫的腳本定義了數(shù)據(jù)庫表的結(jié)構(gòu),例如表包含哪些字段等。類的實例與數(shù)據(jù)的行以相似的方式存儲數(shù)據(jù)。通常一個類可以映射為一個或一個以上的關(guān)系數(shù)據(jù)庫的表,類屬性將映射成關(guān)系數(shù)據(jù)庫中的字段,而對象間的關(guān)系可以通過使用關(guān)系數(shù)據(jù)庫中的外鍵來維護。對象關(guān)系映射的解決方案一般是把每個對象映射到數(shù)據(jù)庫表的單個行上,這一行通常來自一個表,也可以由一個表的連接操作產(chǎn)生。
1.ORM中對象與數(shù)據(jù)庫表之間的映射機制
ORM的實現(xiàn)方式也就是O/R Mapping的映射機制,一般有以下幾種情況。
(1)類屬性和數(shù)據(jù)庫的數(shù)據(jù)表與列建立一種隨機的映射關(guān)系
也就是說,對象類和數(shù)據(jù)庫表并非一一對應,同時對象類中的屬性也不是與數(shù)據(jù)庫表中的列并非一一對應。一個類屬性可對應1或多個實體表的字段。同樣,一個實體表可以對應1個或多個實體類的屬性。這種實現(xiàn)模式主要還是根據(jù)業(yè)務邏輯來劃分對象的,一方面一個業(yè)務邏輯類可以獲取一個數(shù)據(jù)庫表的一部分字段,同時還要獲取另一個或幾個數(shù)據(jù)庫表的部分或全部字段。另一方面一個數(shù)據(jù)庫表可以映射成為多個對象,分別應用在多個業(yè)務實體類中。這種方式的好處有兩點,一是映射的對象結(jié)構(gòu)簡單、易于使用,二是避免每次構(gòu)造對象的時候傳送大量的不相關(guān)的數(shù)據(jù)。
當然,基于這種模式,存在實現(xiàn)對象在數(shù)據(jù)庫中的唯一標識的問題。其實這有兩種解決方案,第一種解決方案還是采用數(shù)據(jù)庫主鍵來實現(xiàn)唯一標識。如果一個實體類映射的是一個數(shù)據(jù)庫表,可以采用數(shù)據(jù)庫表的主鍵來形成實體類的唯一標識。如果一個實體類映射的是多個數(shù)據(jù)庫表,可以把多個數(shù)據(jù)庫表的主鍵組合形成一個實體類的唯一標識。第二種解決方案是采用無業(yè)務意義的字段OID作為各個實體對象的主鍵。這樣OID也作為類與數(shù)據(jù)庫映射時的對象的唯一標識。
(2)實體類和數(shù)據(jù)庫表一一映射
這是一種最簡單的實現(xiàn)模式,即數(shù)據(jù)庫表與對象一對一,即一個數(shù)據(jù)庫表映射為一個Java對象。所有的表字段(field)映射為Java對象的屬性(attribute)。但是不同層次的實體類映射到數(shù)據(jù)表時,應根據(jù)數(shù)據(jù)庫表的關(guān)系來進行。這樣也有三種模式。
① 一個類層次對應一個數(shù)據(jù)表
這里所說的一個類層次,指的是父類及其所有子類。將父類和子類中有持久性需求的屬性設置為同一數(shù)據(jù)表的字段。此方法實現(xiàn)起來簡單,并且較好地支持多態(tài)。因為不同的子類可以用一個標志位加以區(qū)分。子類實例的轉(zhuǎn)換比較容易實現(xiàn),但是,類與數(shù)據(jù)庫之間的耦合程度高。由于子類所特有的屬性被所有類層次中的對象所共有,數(shù)據(jù)庫中冗余字段較多。
② 一個實體類對應一個數(shù)據(jù)表
各個子類所特有的屬性,聯(lián)合從父類中繼承的公共屬性,構(gòu)成表的結(jié)構(gòu)。父類不映射為數(shù)據(jù)庫中的實體表,它只作為子類公共屬性的載體。這種映射模型使得類屬性值的保存和對象還原實現(xiàn)方便。缺點同樣是類結(jié)構(gòu)與數(shù)據(jù)庫的耦合程度高,特別在父類屬性變列時,所有從此繼承下來的子類都需要進行變更。此外,對多態(tài)性的支持也較差。子類的角色轉(zhuǎn)換需要在子類對應的數(shù)據(jù)表之間準確地傳遞適當?shù)膶傩灾担瑫r,需要賦予新的OID。這種情況下,就不如第一種映射模型,用同一個OID,在同一張表內(nèi)就可以實現(xiàn)不同子類之間的轉(zhuǎn)換。
③ 一個類對應一個數(shù)據(jù)表
無論是父類還是子類,只要類中的屬性有持久性保存的需要,就將類映射到數(shù)據(jù)表。子類的表以父類類表的OID為外鍵。在關(guān)系數(shù)據(jù)庫中最大程度地實現(xiàn)了類的多態(tài)性。與前兩者比較,對象與數(shù)據(jù)庫的耦合程度是最低的,某一個類屬性的變更引起的表結(jié)構(gòu)變動最少。這種方法的缺點在于生成子類實例時,繼承層次多的子類的屬性值還原很困難。由于子類的公共屬性包含在父類對應的數(shù)據(jù)表中,當需要單獨獲取子類實例時,需要從多個數(shù)據(jù)表中獲取數(shù)據(jù)合成完整的實例。當類的層次較多時,子類的訪問可能會成為系統(tǒng)與數(shù)據(jù)庫交互的瓶頸。
(3)實體類和數(shù)據(jù)庫視圖映射
第3種映射方式是根據(jù)數(shù)據(jù)庫視圖來構(gòu)造對象,數(shù)據(jù)庫視圖是一種虛擬表,它可以合并多個數(shù)據(jù)庫表,然后再把這個數(shù)據(jù)庫視圖映射成一個實體對象。最為常見的是在數(shù)據(jù)庫中體現(xiàn)為主從表的結(jié)構(gòu),映射成一個實體對象。
2.類間關(guān)系映射為鍵值
數(shù)據(jù)庫表的約束決定了實體類關(guān)系中的關(guān)聯(lián)和聚合。
一對一、一對多的關(guān)聯(lián)是通過在關(guān)聯(lián)的某一方(一般在關(guān)聯(lián)角色多重性≥l的一方)引用對方的OID,并根據(jù)關(guān)系的緊密程度為外鍵的字段加上非空以及唯一性的約束。在生成相關(guān)聯(lián)的類實例時,可根據(jù)外鍵自動獲取另一方的實例。多對多的關(guān)聯(lián)需要創(chuàng)建關(guān)聯(lián)表。關(guān)聯(lián)表是統(tǒng)一的以OID作為主鍵,同時以關(guān)聯(lián)角色雙方的OID作為聯(lián)合外鍵。
聚合關(guān)系映射到數(shù)據(jù)庫中與通常所說的主附表結(jié)構(gòu)類似,在聚合關(guān)系中的子類對應的數(shù)據(jù)表中含有指明父類的OID的域。特別是強制型聚合(或稱之為組合),子類單獨存在是沒有意義的,必須與父類同時存在、同時消亡。當然,數(shù)據(jù)庫鍵值本身只是這一關(guān)系的體現(xiàn)。
數(shù)據(jù)庫表之間主鍵外鍵關(guān)聯(lián)映射的關(guān)系對象模型中存在著三種關(guān)系,分別是一對一、一對多、多對多。體現(xiàn)在數(shù)據(jù)庫中分別是一個主鍵對應一個外鍵,一個主鍵對應多個外鍵,中間表(join table)。
① 一對一:這種情況可以直接映射成在對象之間保持一個引用關(guān)系,一個對象持有對另一個對象的引用。具體體現(xiàn)在對象中實現(xiàn)一個方法,該方法的返回值即它的一對一關(guān)聯(lián)對象。如果這種關(guān)系是雙向的,那么必須在兩個對象中都實現(xiàn)這樣一個方法,如果關(guān)系是單向的,那么由方向性決定在哪個對象中實現(xiàn)。
② 一對多:這種關(guān)系有兩種類型,分別是關(guān)聯(lián)(association)和聚合(aggregation)。對于關(guān)聯(lián),仍然體現(xiàn)為引用關(guān)系。不同于一對一的是,一方對象持有的是一個集合的引用,該集合中的元素是多方對象,多方對象持有的是一方對象的引用。一方對象實現(xiàn)的方法的返回值是一個集合,集合中的元素是多方對象;多方對象實現(xiàn)的方法的返回值就是一方對象。當然可根據(jù)業(yè)務需求決定關(guān)系的方向性,從而決定在哪個對象中實現(xiàn)對應的方法。對于聚合,需要在一方對象中增加一個集合的屬性,該集合中的元素為多方對象。同時一方對象的增、改、刪、查也要加入相應的操作以實現(xiàn)多方對象的對應操作。而多方對象的實現(xiàn)可以根據(jù)實際需求來決定是否需要實現(xiàn)獨立的增、改、刪、查方法。
③ 多對多:這種關(guān)系可以看作是一個雙向的一對多,都把自己看作是一方,對方看作是多方。兩個對象分別持有一個集合的引用,集合中的元素即為對方對象。如果將數(shù)據(jù)庫的中間表映射成一個對象,那么可以將多對多關(guān)系的兩個對象分別實現(xiàn)為對應中間表對象的一對多,即這兩個對象都看作是一方,而中間表對象則看作是多方。從而利用一對多的實現(xiàn)方式去實現(xiàn)這種關(guān)系。
3.面向?qū)ο蟛僮饔成錇閿?shù)據(jù)庫操作
ORM框架的一項重要工作就是將對數(shù)據(jù)庫的操作封裝成實體類的方法。其好處就在于封裝了操作的細節(jié),開發(fā)人員根本不用關(guān)心如何去連接數(shù)據(jù)庫,如何發(fā)送SQL語句,如何取各個字段,他只需調(diào)用一個CRUD(Create、Read、Update和Delete)方法,該方法完成一系列的底層操作,返回的是一個構(gòu)造好的對象,然后他就可調(diào)用相應的get方法取得他所需要的字段的數(shù)值。
ORM框架的方法也就是增、改、刪、查等基本操作,而實體對象屬性也是由數(shù)據(jù)庫表中的字段所構(gòu)成的。ORM框架在構(gòu)造過程中,實際上把CRUD方法,根據(jù)對象屬性與數(shù)據(jù)庫表的映射字段轉(zhuǎn)化為數(shù)據(jù)庫操作中的insert、select、update和delete等SQL語句。
4.事務管理
由于ORM框架封裝了數(shù)據(jù)庫的存儲操作,軟件開發(fā)人員不能處理底層存儲細節(jié),沒有利用數(shù)據(jù)庫的事務管理機制的可能。可以通過兩種辦法解決這個問題,一是采用獨立的事務處理機制,不采用數(shù)據(jù)庫本身的事務管理。二是在映射對象中重載多個保存方法,仍然采用數(shù)據(jù)庫的事務管理機制,使得某一個重載的方法可以提供給軟件開發(fā)人員事務處理的能力。在Java語言中,可以由軟件開發(fā)人員提供一個java.sql.Connection接口,將這個接口作為一個參數(shù)傳給保存的方法,從而可以使得軟件開發(fā)人員有手工控制事務的可能。
5.ORM的性能
ORM框架需要頻繁地跟數(shù)據(jù)庫交互,以下幾個方面對性能有影響。
① 數(shù)據(jù)庫的連接:數(shù)據(jù)庫的連接對象是非常昂貴的資源,不同的獲取數(shù)據(jù)庫連接的方式將對性能產(chǎn)生極大的影響。這可以采用連接池的辦法來解決,每次從連接池中獲取數(shù)據(jù)庫連接,將極大地提高性能。
② 大量數(shù)據(jù)的傳輸:由于應用程序使用的是對象,而對已有數(shù)據(jù)庫記錄的對象的生成需要構(gòu)造它的所有屬性,也就是要將該條記錄所有字段的數(shù)值賦給這個對象。而業(yè)務邏輯有可能僅僅關(guān)心其中幾個字段的數(shù)值,其他字段數(shù)值的傳輸可以說是浪費的,因而可以采用分段獲取的模式。
③ 對象的頻繁獲取:每次應用程序使用已有的持久化對象都要查詢一次數(shù)據(jù)庫,然后構(gòu)造這個對象,對于需要頻繁使用的對象來說,每次都需要查詢數(shù)據(jù)庫。對于這種情況,可以采用緩沖的機制,將一些頻繁使用的對象緩沖起來,再次使用的時候先從緩沖池里面查找,如果沒有找到,然后再查詢數(shù)據(jù)庫。
1.2.3 常用的ORM框架
常見的ORM框架包括Hibernate、iBATIS、TopLink、Castor JDO、Apache OJB等,分別介紹如下。
1.Hibernate
Hibernate是一個開放源代碼的O/R Mapping(對象關(guān)系映射框架),它對JDBC進行了輕量級的對象封裝,使Java程序員可以隨心所欲地使用對象編程思維來操縱數(shù)據(jù)庫。其官方網(wǎng)址:http://www.hibernate.org。
2.iBATIS
iBATIS也是開放源代碼的O/R Mapping,但這是一種“半自動化”的ORM實現(xiàn)。所謂“半自動”,iBATIS以SQL開發(fā)的工作量和數(shù)據(jù)庫移植性方面的讓步,為系統(tǒng)設計提供了更大的自由空間。其官方網(wǎng)址:http://ibatis.apache.org/。
3.TopLink
TopLink是Java對象關(guān)系可持續(xù)性體系結(jié)構(gòu),原屬于WebGain公司的產(chǎn)品,現(xiàn)在被Oracle收購,并重新包裝為Oracle AS TopLink。TopLink為在關(guān)系數(shù)據(jù)庫表中存儲Java對象和企業(yè)Java組件(EJB)提供了高度靈活和高效的機制。TopLink提供了一個持久性基礎(chǔ)架構(gòu),使開發(fā)人員能夠?qū)碜远喾N體系結(jié)構(gòu)的數(shù)據(jù)(包括EJB、CMP和BMP)、POJO、servlet、JSP、會話Bean和消息驅(qū)動(Bean)集成在一起。
4.Entity Bean
Entity Bean它提供了一個持久性數(shù)據(jù)的面向?qū)ο蟮谋硎尽2煌趯ο箨P(guān)系映射,Entity Bean對于關(guān)系數(shù)據(jù)庫沒有限制;它描述的持久性信息可以來自一個企業(yè)信息系統(tǒng)(EIS)或者其他的存儲設備。
5.Castor JDO
Castor JDO是ExoLab Group下面的一個開放源代碼的項目,它最大的特色就是實現(xiàn)了大部分的ODMG OQL規(guī)范,其原理是通過Java反射API去實現(xiàn)屬性的設置和讀取。它的主要API和數(shù)據(jù)接口為:JDO-like、SQL、OQL、JDBC、LDAP、XML、DSML。它支持分布式目錄事務處理和時間;提供處理XML、Directory、XADirectory的類庫,提供從XML到Java類的轉(zhuǎn)換機制。其官方網(wǎng)址:http://castor.exolab.org。
6.Apache OJB
Apache OJB(Object Relational Bridge)是Apache下面的一個開放源代碼的項目。Apache OJB是一種對象關(guān)系映射工具,能夠完成從Java對象到關(guān)系數(shù)據(jù)庫的透明存儲。OJB使用基于XML的對象關(guān)系映射,映射發(fā)生在一個動態(tài)的元數(shù)據(jù)層,使得通過一個簡單的元對象協(xié)議(MOP)在運行時就可以操作元數(shù)據(jù)層去改變存儲內(nèi)核。其官方網(wǎng)址:http://db.apache.org/ojb/。
7.Torque
Apache Torque是一個使用關(guān)系數(shù)據(jù)庫作為存儲手段的Java應用程序持久化工具。Torque是Apache下面的一個開源項目,由Web應用程序框架Jakarta Apache Turbine發(fā)展而來,但現(xiàn)在已完全獨立于Turbine。
1.2.4 ORM模型和持久層框架
現(xiàn)在很多書籍都把ORM模型和持久層作為一個概念來進行說明。筆者認為這兩者還是有區(qū)別的。這里有幾個基本概念要區(qū)分,包括持久化、持久層、ORM等。
持久化,英文即“Persistence”,就是把內(nèi)存中的數(shù)據(jù)對象保存到可永久保存的存儲設備中。持久主要應用是將內(nèi)存中的數(shù)據(jù)存儲在關(guān)系型的數(shù)據(jù)庫中,當然也可以指存儲在磁盤文件等。持久層就是專注于實現(xiàn)數(shù)據(jù)持久化應用領(lǐng)域的某個特定系統(tǒng)的一個邏輯層面,將數(shù)據(jù)使用者和數(shù)據(jù)實體相關(guān)聯(lián)。
O/R Mapping是把對數(shù)據(jù)表映射為對象類,或者把對象類映射為數(shù)據(jù)表。
在細微的比較上兩者還是有一點差異的。
① ORM模型主要是實現(xiàn)對象和關(guān)系數(shù)據(jù)直接的映射。持久層是對象處理和關(guān)系數(shù)據(jù)庫處理中的一個交互層,在這個交互層主要是實現(xiàn)內(nèi)存數(shù)據(jù)與硬盤數(shù)據(jù)的一致性和統(tǒng)一性。
② ORM模型是一種實現(xiàn)手段,而持久層是一種實現(xiàn)技術(shù)。
③ 持久層框架的概念要比ORM模型框架要大,即持久層框架一般都是包括ORM框架,而ORM只是實現(xiàn)持久化技術(shù)中的一種。
從嚴格意義上來講,iBATIS應該趨向于是ORM框架。這樣才歸屬持久層框架。在這里簡單地介紹一下幾種持久層框架的實現(xiàn)方式。
① 主動域的對象模式
主動域的對象模式是在實現(xiàn)中封裝了關(guān)系數(shù)據(jù)模型和數(shù)據(jù)訪問細節(jié)的一種形式。在J2EE架中,EJB組件分為會話EJB和實體EJB。會話EJB通常實現(xiàn)業(yè)務邏輯,而實體EJB表示業(yè)務實體。實體EJB又分為兩種:由EJB本身管理持久化,即BMP(Bean-Managed Persistence);有EJB容器管理持久化,即CMP(Container-Managed Persistence)。BMP就是主動域?qū)ο竽J降囊粋€例子,BMP表示由實體EJB自身管理數(shù)據(jù)訪問細節(jié)。主動域?qū)ο蟊旧砦挥跇I(yè)務邏輯層,因此采用主動域?qū)ο竽J綍r,整個應用仍是三層應用結(jié)構(gòu),并沒有從業(yè)務邏輯層分離出獨立的持久化層。
② JDO模式
JDO(Java Data Objects)規(guī)范是Sun公司制定的描述對象持久化語義的標準。嚴格地說,JDO并不是對象-關(guān)系映射接口,因為它支持把對象持久化到一種存儲系統(tǒng)中,包括關(guān)系數(shù)據(jù)庫、面向?qū)ο蟮臄?shù)據(jù)庫、基于XML的數(shù)據(jù)庫,以及其他專有存儲系統(tǒng)。由于關(guān)系數(shù)據(jù)庫是目前最流行的存儲系統(tǒng),故許多JDO的實現(xiàn)都包含了對象-關(guān)系映射服務。
③ CMP模式
在J2EE架構(gòu)中,CMP(Container-Managed Persistence)表示由EJB容器來管理實體EJB的持久化,EJB容器封裝了對象-關(guān)系的映射及數(shù)據(jù)訪問細節(jié)。CMP和ORM的相似之處在于,兩者都提供對象-關(guān)系映射服務,都把對象持久化的任務從業(yè)務邏輯中分離出來。區(qū)別在于CMP負責持久化實體EJB組件,而ORM負責持久化POJO,它是基于普通的JavaBean形式的實體域?qū)ο蟆?/p>
- 邊做邊學:Photoshop CS6 圖像制作案例教程
- Midjourney從入門到實戰(zhàn)應用
- 魔法詞典:AI繪畫關(guān)鍵詞圖鑒(Stable Diffusion版)
- 無師自通AutoCAD:中文版室內(nèi)設計
- Photoshop+Adobe Camera Raw+Lightroom(攝影后期照片潤飾實戰(zhàn))
- 中文版3ds Max 2021完全自學教程
- SolidWorks 2018有限元:運動仿真與流場分析自學手冊
- 音樂制作7天速成:Cubase編曲教程
- 行攝 Photoshop CC后期修片高手之道(第2版)
- Scribus 1.3.5: Beginner's Guide
- 中文版3ds Max 2014-VRay效果圖制作完全自學教程
- Premiere Pro基礎(chǔ)與實戰(zhàn)教程
- 零基礎(chǔ)學Photoshop CS6(全視頻教學版)
- Joomla! with Flash
- Photoshop+Firefly從入門到精通