




已閱讀5頁(yè),還剩15頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
煙臺(tái)華東電子軟件技術(shù)有限公司第8章 hibernate數(shù)據(jù)源層O/R Mapping主要介紹三層架構(gòu),如何分層?(邏輯上的分層,二個(gè)原則)數(shù)據(jù)層技術(shù)的選擇:直接使用SQL/JDBC:優(yōu)點(diǎn):很多開(kāi)發(fā)者熟悉關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng),理解SQL,也知道如何使用表和外鍵進(jìn)行工作。此外,他們可以始終使用眾所周知并廣泛使用的DAO設(shè)計(jì)模式對(duì)業(yè)務(wù)邏輯隱藏復(fù)雜的JDBC代碼和不可移植的SQL。缺點(diǎn):為域中的每個(gè)類(lèi)手工編寫(xiě)持續(xù)性代碼的工作是非常可觀的,特別是需要支持多種SQL方言時(shí)。這項(xiàng)工作通常會(huì)消耗很大一部分的開(kāi)發(fā)努力。此外,當(dāng)需求改變時(shí),一個(gè)手工編碼的解決方案總是需要更多的注意和維護(hù)努力。序列化:Java有一個(gè)內(nèi)建的持久化機(jī)制:序列化提供了將對(duì)象圖(應(yīng)用狀態(tài))寫(xiě)到字節(jié)流中的能力,然后它可能被持久化到文件或數(shù)據(jù)庫(kù)中。持久化也被Java的遠(yuǎn)程方法調(diào)用(RMI)使用來(lái)為復(fù)雜對(duì)象傳遞值語(yǔ)義。持久化的另一種用法是在機(jī)器集群中跨節(jié)點(diǎn)復(fù)制應(yīng)用狀態(tài)。缺點(diǎn):很不幸,一個(gè)相互連接的對(duì)象圖在序列化之后只能被當(dāng)作一個(gè)整體訪問(wèn),如果不反序列化整個(gè)流就不可能從流中取出任何數(shù)據(jù)。這樣,結(jié)果字節(jié)流肯定會(huì)被認(rèn)為不適合進(jìn)行任意的檢索或聚合。甚至不可能獨(dú)立地訪問(wèn)或更新一個(gè)單獨(dú)的對(duì)象或子圖。非常明顯,因?yàn)楫?dāng)前特定的技術(shù),序列化不適合于作為高并發(fā)性的Web和企業(yè)應(yīng)用的持久化機(jī)制。在特定的環(huán)境中它被作為桌面應(yīng)用的適當(dāng)?shù)某志没瘷C(jī)制。EJB entity beansEJB1.1實(shí)體Bean在實(shí)踐中徹底地失敗了。EJB規(guī)范的設(shè)計(jì)缺陷阻礙了Bean管理的持續(xù)性(BMP)實(shí)體Bean有效地執(zhí)行。在EJB1.1許多明顯的缺陷被糾正之后,一個(gè)邊緣的稍微可接受的解決方案是容器管理的持續(xù)性(CMP)。然而,CMP并不能表示一種對(duì)象-關(guān)系不匹配的解決方案。CMP缺點(diǎn): CMP實(shí)體Bean的粒度既太粗又太細(xì):CMP Bean與關(guān)系模型中的表是按照一對(duì)一的方式定義的。這樣,它們的粒度過(guò)粗,不能夠完全利用Java豐富的類(lèi)型。 雖然EJB可以利用繼承實(shí)現(xiàn),但實(shí)體Bean并不支持多態(tài)的關(guān)聯(lián)和查詢(xún) 不管EJB規(guī)范所宣稱(chēng)的目標(biāo),實(shí)體Bean實(shí)際上是不可移植的。CMP引擎的性能因廠商而異,并且映射元數(shù)據(jù)也是高度特定于廠商的。 實(shí)體Bean不可序列化。我們發(fā)現(xiàn)當(dāng)我們需要將數(shù)據(jù)傳輸?shù)竭h(yuǎn)程客戶(hù)層時(shí),我們必須定義額外的數(shù)據(jù)傳輸對(duì)象(DTO,也被稱(chēng)作值對(duì)象) 實(shí)體Bean必須依賴(lài)于EJB容器測(cè)試?yán)щy。JDO、Object-oriented database systems大多數(shù)面向?qū)ο蟮臄?shù)據(jù)庫(kù)系統(tǒng)對(duì)ODMG標(biāo)準(zhǔn)都提供了許多程度的支持,但據(jù)我們所知,還沒(méi)有完全的實(shí)現(xiàn)。此外,在規(guī)范發(fā)布以后的很多年,甚至到了3.0版,還是感覺(jué)不太成熟,并且缺乏很多有用的特征,特別是基于Java環(huán)境的。ODMG也不再活躍。最近,Java數(shù)據(jù)對(duì)象(JDO)規(guī)范(發(fā)表于2002年4月)揭開(kāi)了新的可能性。JDO由面向?qū)ο髷?shù)據(jù)庫(kù)團(tuán)體的成員驅(qū)動(dòng),除了對(duì)現(xiàn)有的ODMG的支持之外,面向?qū)ο蟮臄?shù)據(jù)庫(kù)產(chǎn)品現(xiàn)在還經(jīng)常將其作為主要的API采用。JDO 的優(yōu)點(diǎn)在于它很簡(jiǎn)單。開(kāi)發(fā)人員使用 Java 語(yǔ)言持久存儲(chǔ)對(duì)象實(shí)例并從存儲(chǔ)器檢索實(shí)例。處理邏輯、同步和故障轉(zhuǎn)移等均被透明地處理。開(kāi)發(fā)人員無(wú)需使用 SQL 或 Java 語(yǔ)言提供的不便的序列化機(jī)制,只使用 POJO(無(wú)格式普通 Java 對(duì)象)即可,利用 JDO 接口將對(duì)象引用傳遞到存儲(chǔ)器中并從存儲(chǔ)器檢索對(duì)象引用。O/R Mapping什么是O/R Mapping?它有什么優(yōu)點(diǎn)?簡(jiǎn)單地說(shuō),對(duì)象-關(guān)系映射就是Java應(yīng)用中的對(duì)象到關(guān)系數(shù)據(jù)庫(kù)中的表的自動(dòng)的(和透明的)持久化,使用元數(shù)據(jù)(meta data)描述對(duì)象與數(shù)據(jù)庫(kù)間的映射。本質(zhì)上,ORM的工作是將數(shù)據(jù)從一種表示(雙向)轉(zhuǎn)換為另一種。提高生產(chǎn)率(Productivity)與持久性有關(guān)的代碼可能是Java應(yīng)用中最乏味的代碼。Hibernate去掉了很多讓人心煩的工作(多于你的期望),讓你可以集中更多的精力到業(yè)務(wù)問(wèn)題上。不論你喜歡哪種應(yīng)用開(kāi)發(fā)策略自頂向下,從域模型開(kāi)始;或者自底向上,從一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)模式開(kāi)始使用Hibernate和適當(dāng)?shù)墓ぞ邔?huì)減少大量的開(kāi)發(fā)時(shí)間??删S護(hù)性(Maintainability) 減少了代碼,重構(gòu)更方便,提高了可維護(hù)性。ORM是對(duì)象和關(guān)系數(shù)據(jù)庫(kù)之間的緩沖區(qū),用來(lái)很好的將他們隔離。更好性能(Performance)ORM軟件的實(shí)現(xiàn)人員可能有比你更多的時(shí)間來(lái)研究性能優(yōu)化問(wèn)題。你知道嗎,例如,緩存PreparedStatement的實(shí)例對(duì)DB2的JDBC驅(qū)動(dòng)導(dǎo)致了一個(gè)明顯的性能增長(zhǎng)但卻破壞了InterBase的JDBC驅(qū)動(dòng)?你了解嗎,對(duì)某些數(shù)據(jù)庫(kù)只更新一個(gè)表中被改變的字段可能會(huì)非常快但潛在地對(duì)其它的卻很慢?在你手工編寫(xiě)的解決方案中,對(duì)這些不同策略之間的沖突進(jìn)行試驗(yàn)是多么不容易呀?廠商獨(dú)立性(Vendor independence)ORM抽象了你的應(yīng)用使用下層SQL數(shù)據(jù)庫(kù)和SQL方言的方式。如果工具支持許多不同的數(shù)據(jù)庫(kù)(dialect),那么這會(huì)給你的應(yīng)用帶來(lái)一定程度的可移植性。你不必期望可以達(dá)到“一次編寫(xiě),到處運(yùn)行”,因?yàn)閿?shù)據(jù)庫(kù)的性能不同并且達(dá)到完全的可移植性需要犧牲更強(qiáng)大的平臺(tái)的更多的力氣。然而,使用ORM開(kāi)發(fā)跨平臺(tái)的應(yīng)用通常更容易。即使你不需要跨平臺(tái)操作,ORM依然可以幫你減小被廠商鎖定的風(fēng)險(xiǎn)。另外,數(shù)據(jù)庫(kù)獨(dú)立性對(duì)這種開(kāi)發(fā)情景也有幫助:開(kāi)發(fā)者使用一個(gè)輕量級(jí)的本地?cái)?shù)據(jù)庫(kù)進(jìn)行開(kāi)發(fā)但實(shí)際產(chǎn)品需要配置在一臺(tái)不同的數(shù)據(jù)庫(kù)上。如何做對(duì)象關(guān)系數(shù)據(jù)庫(kù)映射?(最后引入Hibernate)public class User private Long id;private String name;private List address;create table tbl_user (id bigint not null auto_increment, name varchar(255), primary key (id)Java數(shù)據(jù)庫(kù)類(lèi)的屬性(基本類(lèi)型)表的列類(lèi)表1:n/n:1外鍵n:m關(guān)聯(lián)表繼承單表繼承、具體表繼承、類(lèi)表繼承1、 Java基本類(lèi)型表的2、 Java類(lèi)的映射3、 關(guān)聯(lián)的映射:例如一個(gè)User有多個(gè)Address,User和Address管理,User刪除時(shí),相應(yīng)的Address也應(yīng)該刪除。對(duì)象關(guān)系的不匹配范式(paradigm)1、 粒度(granularity)的問(wèn)題。 增加一種新的數(shù)據(jù)類(lèi)型,將Java地址對(duì)象在我們的數(shù)據(jù)庫(kù)中保存為單獨(dú)的一列,聽(tīng)起來(lái)好像是最好的方法。畢竟,Java中的一個(gè)新的地址類(lèi)與SQL數(shù)據(jù)類(lèi)型中的一個(gè)新的地址類(lèi)型可以保證互用性。然而,如果你檢查現(xiàn)在的數(shù)據(jù)庫(kù)管理系統(tǒng)對(duì)用戶(hù)定義列類(lèi)型(UDT)的支持,你將會(huì)發(fā)現(xiàn)各種各樣的問(wèn)題。2、 子類(lèi)型(subtypes)的問(wèn)題。 子類(lèi)型不匹配是指Java模型中的繼承結(jié)構(gòu)必須被持續(xù)化到SQL數(shù)據(jù)庫(kù)中,而SQL數(shù)據(jù)庫(kù)并沒(méi)有提供一個(gè)支持繼承的策略。如何解決多態(tài)?3、 同一性(identity)的問(wèn)題Java對(duì)象定義了兩種不同的相等性的概念: 對(duì)象同一性(粗略的等同于內(nèi)存位置的相等,使用a=b檢查) 通過(guò)equals()方法的實(shí)現(xiàn)來(lái)決定的相等性(也被稱(chēng)作值相等)另一方面,數(shù)據(jù)庫(kù)行的同一性使用主鍵值表示。主鍵既不必然地等同于“equals()”也不等同于“=”。它通常是指幾個(gè)對(duì)象(不相同的)同時(shí)表示了數(shù)據(jù)庫(kù)中相同的行。而且,為一個(gè)持續(xù)類(lèi)正確地實(shí)現(xiàn)equals()方法包含許多微妙的難點(diǎn)。4、 與關(guān)聯(lián)(associations)有關(guān)的問(wèn)題面向?qū)ο蟮恼Z(yǔ)言使用對(duì)象引用和對(duì)象引用的集合表示關(guān)聯(lián)。在關(guān)系世界里,關(guān)聯(lián)被表示為外鍵列,外鍵是幾個(gè)表的鍵值的拷貝。這兩種表示之間有些微妙的不同。5、 對(duì)象結(jié)構(gòu)導(dǎo)航的問(wèn)題在Java中訪問(wèn)對(duì)象的方式與在關(guān)系數(shù)據(jù)庫(kù)中有根本的不同。在Java中,訪問(wèn)用戶(hù)的賬單信息時(shí),你調(diào)用aUser.getBillingDetails().getAccountNumber()。這是最自然的面向?qū)ο髷?shù)據(jù)的訪問(wèn)方式,通常被形容為遍歷對(duì)象圖。根據(jù)實(shí)例間的關(guān)聯(lián),你從一個(gè)對(duì)象導(dǎo)航到另一個(gè)對(duì)象。不幸地是,這不是從SQL數(shù)據(jù)庫(kù)中取出數(shù)據(jù)的有效方式。為了提高數(shù)據(jù)訪問(wèn)代碼的性能,唯一重要的事是最小化數(shù)據(jù)庫(kù)請(qǐng)求的次數(shù)。最明顯的方式是最小化SQL查詢(xún)的數(shù)量(其它方式包括使用存儲(chǔ)過(guò)程或者JDBC批處理API)。使用SQL有效地訪問(wèn)關(guān)系數(shù)據(jù)通常需要在有關(guān)的表之間使用連接。在連接中包含的表的數(shù)量決定了你可以導(dǎo)航的對(duì)象圖的深度。性能:N+1的問(wèn)題 范式不匹配的代價(jià):1、花費(fèi)很多時(shí)間和精力來(lái)手工解決對(duì)象和關(guān)系的不匹配。2、為了解決不匹配,甚至要扭曲對(duì)象模型直到它與下層的關(guān)系技術(shù)匹配為止4、 JDBC API本身的問(wèn)題。JDBC和SQL提供了一個(gè)面向語(yǔ)句(即命令)的方法從SQL數(shù)據(jù)庫(kù)中來(lái)回移動(dòng)數(shù)據(jù)。至少在三個(gè)時(shí)刻(Insert,Update,Select)必須指定一個(gè)結(jié)構(gòu)化關(guān)系,這增加了設(shè)計(jì)和實(shí)現(xiàn)所需要的時(shí)間。主流持久層框架縱覽目前眾多廠商和開(kāi)源社區(qū)都提供了持久層框架實(shí)現(xiàn),常見(jiàn)的有:Apache OJB(/ojb/ )Cayenne(/cayenne/ )Jaxor( )Hibernate()iBATIS( )jRelationalFramework()mirage(/en/oss/mirage/toon)SMYLE(http:/www.drjava.de/smyle/)TopLink(/products/ias/toplink/index.html )(其中TopLink 是Oracle 的商業(yè)產(chǎn)品。其他均為開(kāi)源項(xiàng)目)Apache OJB 的優(yōu)勢(shì)在于對(duì)各種標(biāo)準(zhǔn)的全面支持(不過(guò)事實(shí)上,我們的系統(tǒng)研發(fā)中并不需要同時(shí)支持這么多標(biāo)準(zhǔn),追求多種標(biāo)準(zhǔn)的并行支持本身也成為Apache OJB 項(xiàng)目發(fā)展的沉重包袱),且其從屬于Apache 基金組織,有著可靠的質(zhì)量保證和穩(wěn)定的發(fā)展平臺(tái)。Hibernate 在2003 年末被JBoss 組織收納,成為從屬于JBoss 組織的子項(xiàng)目之一,從而贏得了良好的發(fā)展前景(同時(shí)榮獲Jolt 2004 大獎(jiǎng))。Hibernate 與OJB 設(shè)計(jì)思想類(lèi)似,具備相近的功能和特色,但由于其更加靈活快速的發(fā)展策略,得到了廣大技術(shù)人員的熱情參與,因此也得到了更廣泛的推崇。相對(duì)ApacheOJB 遲鈍的項(xiàng)目開(kāi)發(fā)進(jìn)度表,Hibernate 活躍的開(kāi)發(fā)團(tuán)隊(duì)以及各社區(qū)內(nèi)對(duì)其熱烈的關(guān)注為其帶來(lái)了極大的活力,并逐漸發(fā)展成Java 持久層事實(shí)上的標(biāo)準(zhǔn)。iBATIS 相對(duì)Apache OJB 和Hibernate 項(xiàng)目則另具特色,iBATIS 采取了更加開(kāi)放式的設(shè)計(jì),通過(guò)iBATIS,我們可以控制更多的數(shù)據(jù)庫(kù)操作細(xì)節(jié)。相對(duì)而言,Hibernate、Apache OJB 對(duì)持久層的設(shè)計(jì)則較為封閉,封閉化的設(shè)計(jì)對(duì)持久層進(jìn)行了較為徹底的封裝,從而將底層細(xì)節(jié)與上層架構(gòu)完全分離,大多數(shù)情況下,特別是對(duì)于新系統(tǒng),新產(chǎn)品的研發(fā)而言,封閉化的設(shè)計(jì)帶來(lái)了更高的開(kāi)發(fā)效率和更好的封裝機(jī)制,但是在某些情況下,卻又為一些必須的底層調(diào)整帶來(lái)了阻力,如在對(duì)遺留系統(tǒng)的改造和對(duì)既有數(shù)據(jù)庫(kù)的復(fù)用上,表現(xiàn)出靈活性不足的弱點(diǎn)。此時(shí)作為OJB,Hibernate 的一個(gè)有益補(bǔ)充,iBATIS的出現(xiàn)顯得別具意義。Hibernate入門(mén)Hibernate概述Hibernate是非常優(yōu)秀、成熟的O/R Mapping框架。它提供了強(qiáng)大、高性能的Java對(duì)象和關(guān)系數(shù)據(jù)的持久化和查詢(xún)功能。(O/R Mapping是一項(xiàng)實(shí)用的工程技術(shù),把數(shù)據(jù)庫(kù)的E/R模型用java的OO語(yǔ)法描述出來(lái),Hibernate是其中的當(dāng)之無(wú)愧的最耀眼的明星,cglib動(dòng)態(tài)增強(qiáng),多種靈活的class繼承樹(shù)映射機(jī)制,廣泛的社團(tuán)支援,掩蓋了其他項(xiàng)目的光輝。)Hibernate的優(yōu)勢(shì) 開(kāi)源(LGPL) 成熟 流行(約13 000 downloads/month) 自定義APIJBoss 將用Hibernate3實(shí)現(xiàn)Entity Beans使用Hibernate的開(kāi)發(fā)步驟1、 設(shè)計(jì)一般首先進(jìn)行領(lǐng)域?qū)ο蟮脑O(shè)計(jì)。因?yàn)樵贖ibernate中,我們的領(lǐng)域?qū)ο罂梢灾苯映洚?dāng)持久化類(lèi)。2、 映射定義Hibernate的映射文件,實(shí)現(xiàn)持久化類(lèi)和數(shù)據(jù)庫(kù)之間映射。3、 應(yīng)用使用Hibernate提供的API,實(shí)現(xiàn)具體的持久化業(yè)務(wù)。Hibernate的映射Entity-hbm-ddl(數(shù)據(jù)庫(kù))(hbm(hibernate mapping)和ddl(Data Definition Language)的全稱(chēng))之間的互相轉(zhuǎn)換User.java User.hbm.xmlXDoclet:它通過(guò)在Java源代碼中加入特定的JavaDoc tag,從而為其添加特定的附加語(yǔ)義,之后通過(guò)XDoclet工具對(duì)代碼中JavaDoc Tag進(jìn)行分析,自動(dòng)生成與代碼對(duì)應(yīng)的配置文件(/)。XDoclet提供了對(duì)Hibernate的支持,這樣我們可以直接由Java代碼生成Hibernate映射文件。Middlegen: 用來(lái)從數(shù)據(jù)庫(kù)中已有的表結(jié)構(gòu)中生成Hibernate映射文件。當(dāng)前版本是2.1可以去http:/boss.bekk.no/boss/middlegen下載。Hibernate核心接口Configuration:正如其名,Configuration 類(lèi)負(fù)責(zé)管理Hibernate 的配置信息。Hibernate 運(yùn)行時(shí)需要獲取一些底層實(shí)現(xiàn)的基本信息,其中幾個(gè)關(guān)鍵屬性包括:1、數(shù)據(jù)庫(kù)URL2、數(shù)據(jù)庫(kù)用戶(hù)3、數(shù)據(jù)庫(kù)用戶(hù)密碼4、數(shù)據(jù)庫(kù)JDBC驅(qū)動(dòng)類(lèi)5、 數(shù)據(jù)庫(kù)dialect,用于對(duì)特定數(shù)據(jù)庫(kù)提供支持,其中包含了針對(duì)特定數(shù)據(jù)庫(kù)特性的實(shí)現(xiàn),如Hibernate數(shù)據(jù)類(lèi)型到特定數(shù)據(jù)庫(kù)數(shù)據(jù)類(lèi)型的映射等。當(dāng)然,還有指定Hibernate映射文件的位置。(*.hbm.xml)。Hibernate配置有兩種方法:一、 屬性文件配置。默認(rèn)文件名是perties。調(diào)用代碼: Configuration config = new Configuration();二、 XML文件配置。默認(rèn)文件名是hibernate.cfg.xml。Configuration config = new Configuration().configure();SessionFactory:應(yīng)用程序從SessionFactory(會(huì)話(huà)工廠)里獲得Session(會(huì)話(huà))實(shí)例。它打算在多個(gè)應(yīng)用線程間進(jìn)行共享。通常情況下,整個(gè)應(yīng)用只有唯一的一個(gè)會(huì)話(huà)工廠例如在應(yīng)用初始化時(shí)被創(chuàng)建。然而,如果你使用Hibernate訪問(wèn)多個(gè)數(shù)據(jù)庫(kù),你需要對(duì)每一個(gè)數(shù)據(jù)庫(kù)使用一個(gè)會(huì)話(huà)工廠。會(huì)話(huà)工廠緩存了生成的SQL語(yǔ)句和Hibernate在運(yùn)行時(shí)使用的映射元數(shù)據(jù)。它也保存了在一個(gè)工作單元中讀入的數(shù)據(jù)并且可能在以后的工作單元中被重用(只有類(lèi)和集合映射指定了使用這種二級(jí)緩存時(shí)才會(huì)如此)。SessionFactory sessionFactory = config.buildSessionFactory();Session(會(huì)話(huà)):該接口是Hibernate使用最多的接口。Session不是線程安全的,它代表與數(shù)據(jù)庫(kù)之間的一次操作。Session通過(guò)SessionFactory打開(kāi),在所有的工作完成后,需要關(guān)閉:它的概念介于Connection和Transaction之間。我們可以簡(jiǎn)單的認(rèn)為它是已經(jīng)裝載對(duì)象的緩存或集合的一個(gè)獨(dú)立工作單元。我們有時(shí)也稱(chēng)Session為持久化管理器,因?yàn)樗桥c持久化有關(guān)的操作的接口。Hibernate會(huì)話(huà)并不是線程安全的因此應(yīng)該被設(shè)計(jì)為每次只能在一個(gè)線程中使用。Hibernate會(huì)話(huà)與Web層的HttpSession沒(méi)有任何關(guān)系。Session session = sessionFactory.openSession();Transaction:事務(wù)將應(yīng)用代碼從底層的事務(wù)實(shí)現(xiàn)中抽象出來(lái)這可能是一個(gè)JDBC事務(wù),一個(gè)JTA用戶(hù)事務(wù)或者甚至是一個(gè)公共對(duì)象請(qǐng)求代理結(jié)構(gòu)(CORBA)允許應(yīng)用通過(guò)一組一致的API控制事務(wù)邊界。這有助于保持Hibernate應(yīng)用在不同類(lèi)型的執(zhí)行環(huán)境或容器中的可移植性。Transaction trans = session.beginTransaction ();Query: Query(查詢(xún))接口允許你在數(shù)據(jù)庫(kù)上執(zhí)行查詢(xún)并控制查詢(xún)?nèi)绾螆?zhí)行。查詢(xún)語(yǔ)句使用HQL或者本地?cái)?shù)據(jù)庫(kù)的SQL方言編寫(xiě)。Query query = session.createQuery(“from User”);Lifecycle:Lifecycle接口提供了一些回調(diào)方法,可以讓持久化對(duì)象在save或load之后,或者在delete或update之前進(jìn)行必要的初始化與清除步驟。public interface Lifecycle public boolean onSave(Session s) throws CallbackException; (1) public boolean onUpdate(Session s) throws CallbackException; (2) public boolean onDelete(Session s) throws CallbackException; (3) public void onLoad(Session s, Serializable id); (4)(1) onSave - 在對(duì)象即將被save或者insert的時(shí)候回調(diào) (2) onUpdate - 在對(duì)象即將被update的時(shí)候回調(diào)(也就是對(duì)象被傳遞給Session.update()的時(shí)候) (3) onDelete - 在對(duì)象即將被delete(刪除)的時(shí)候回調(diào) (4) onLoad - 在對(duì)象剛剛被load(裝載)后的時(shí)候回調(diào)Validatable: 該接口是合法性檢查的回調(diào)。如果持久化類(lèi)需要在保存其持久化狀態(tài)前進(jìn)行合法性檢查,它可以實(shí)現(xiàn)下面的接口: public interface Validatable public void validate() throws ValidationFailure;如果發(fā)現(xiàn)對(duì)象違反了某條規(guī)則,應(yīng)該拋出一個(gè)ValidationFailure異常。在Validatable實(shí)例的validate()方法內(nèi)部不應(yīng)該改變它的狀態(tài)。 和Lifecycle接口的回調(diào)方法不同,validate()可能在任何時(shí)間被調(diào)用。應(yīng)用程序不應(yīng)該把validate()調(diào)用和商業(yè)功能聯(lián)系起來(lái)。Interceptor: Interceptor接口提供從session到你的應(yīng)用程序的回調(diào)方法,讓你的程序可以觀察和在持久化對(duì)象保存/更改/刪除或者裝載的時(shí)候操作它的屬性。一種可能的用途是用來(lái)監(jiān)視統(tǒng)計(jì)信息。比如,下面的Interceptor會(huì)自動(dòng)在一個(gè)Auditable創(chuàng)建的時(shí)候設(shè)置其createTimestamp,并且當(dāng)它被更改的時(shí)候,設(shè)置其lastUpdateTimestamp屬性。UserType: 開(kāi)發(fā)者創(chuàng)建屬于他們自己的值類(lèi)型也是很容易的。比如說(shuō),你可能希望持久化java.lang.BigInteger類(lèi)型的屬性,持久化成為VARCHAR字段。Hibernate沒(méi)有內(nèi)置這樣一種類(lèi)型。自定義類(lèi)型能夠映射一個(gè)屬性(或集合元素)到不止一個(gè)數(shù)據(jù)庫(kù)表字段。比如說(shuō),你可能有這樣的Java屬性:getName()/setName(),這是java.lang.String類(lèi)型的,對(duì)應(yīng)的持久化到三個(gè)字段:FIRST_NAME, INITIAL, SURNAME。 要實(shí)現(xiàn)一個(gè)自定義類(lèi)型,可以實(shí)現(xiàn)net.sf.hibernate.UserType或net.sf.hibernate.CompositeUserType中的任一個(gè),并且使用類(lèi)型的Java全限定類(lèi)名來(lái)聲明屬性。請(qǐng)查看net.sf.hibernate.test.DoubleStringType這個(gè)例子,看看它是怎么做的。 注意使用標(biāo)簽來(lái)把一個(gè)屬性映射到多個(gè)字段的做法。用戶(hù)的例子設(shè)計(jì):用戶(hù),id name映射:User.java User.hbm.xml一、安裝二、持久化類(lèi)(Persistent Class)持久化類(lèi)不需要實(shí)現(xiàn)什么特別的接口,也不需要從一個(gè)特別的持久化根類(lèi)繼承下來(lái)。Hibernate也不需要使用任何編譯期處理,比如字節(jié)碼增強(qiáng)操作,它獨(dú)立的使用Java反射機(jī)制和運(yùn)行時(shí)類(lèi)增強(qiáng)(通過(guò)CGLIB)。所以,在Hibernate中,POJO的類(lèi)不需要任何前提條件,我們就可以把它映射成為數(shù)據(jù)庫(kù)表。持久化類(lèi)必須遵循的原則:1、 為類(lèi)的持久化類(lèi)字段申明訪問(wèn)方法(Get/set)。Hibernate對(duì)JavaBeans風(fēng)格的屬性實(shí)行持久化。2、 實(shí)現(xiàn)一個(gè)默認(rèn)的構(gòu)造方法(constructor)。這樣的話(huà)Hibernate就可以使用Constructor.newInstance()來(lái)實(shí)例化它們。3、 如果是集合類(lèi)型的屬性,它的類(lèi)型必須定義為集合的接口。例如:List、Set4、 提供一個(gè)標(biāo)識(shí)屬性(identifier property)。如果沒(méi)有該屬性,一些功能不起作用,比如:級(jí)聯(lián)更新(Cascaded updates)Session.saveOrUpdate()。三、 hibernate映射文件四、應(yīng)用:TestUser.java之后做個(gè)總結(jié),特別是CRUD操作。Hibernate映射聲明(Mapping declaration)一、 DOCTYPE聲明。一個(gè)XML document應(yīng)該在文檔的起始位置有一個(gè)XML的聲明,可能跟隨著一個(gè)DOCTYPE的聲明。一個(gè)DOCTYPE聲明告訴一個(gè)XML parser這個(gè)XML文檔遵循了哪一個(gè)DTD(Document Type Declaration)。Parser可以用此信息來(lái)確認(rèn)這個(gè)XML文檔包含的僅是這個(gè)DTD聲明的XML element。例如:DTD可以從上述URL中獲取,或者在hibernate-x.x.x/src/net/sf/hibernate目錄中,或hibernate.jar文件中找到。Hibernate總是會(huì)在它的classptah中首先搜索DTD文件。二、 hibernate-mapping它是文檔的根(root),可以包含多個(gè)類(lèi)的映射,但一般只包含一個(gè)類(lèi)。(1)、schema(可選):數(shù)據(jù)庫(kù)Schema Name(2)、default-cascade(可選,默認(rèn)為none):默認(rèn)的級(jí)聯(lián)風(fēng)格(3)、auto-import(可選,默認(rèn)為true):是否允許在查詢(xún)語(yǔ)言中使用非完全限定的類(lèi)名即只用類(lèi)的名稱(chēng),不用加入包名(僅限本映射文件中定義的類(lèi))。(4)、package(可選),如果該映射文件中定義的類(lèi)名不包含package,則使用這里定義的package作為類(lèi)名的前綴。注:(3)默認(rèn)的值是“true”,如果有多個(gè)類(lèi)的名字相同,則必須將該值設(shè)為false。三、class用class元素來(lái)定義一個(gè)持久化類(lèi)。1、 name:持久化類(lèi)(或Java接口)的全名。2、 table:對(duì)應(yīng)的數(shù)據(jù)庫(kù)表名。3、 discriminator-value(鑒別值)(可選,默認(rèn)和類(lèi)名一樣):一個(gè)用于區(qū)分不同子類(lèi)的值,在多態(tài)行為中使用。4、 mutable(可選,默認(rèn)值為true):表明該類(lèi)是否可以改變。如果將它設(shè)為false,則應(yīng)用程序不能對(duì)此類(lèi)對(duì)應(yīng)的數(shù)據(jù)進(jìn)行修改和刪除。5、 schema(可選):覆蓋在根元素中指定的schema名字。6、 proxy(可選):指定一個(gè)接口,在延遲裝載時(shí)作為代理使用。你可以在這里使用該類(lèi)自己的名字。7、 dynamic-update(動(dòng)態(tài)更新) (可選,默認(rèn)為false): 指定用于UPDATE 的SQL將會(huì)在運(yùn)行時(shí)動(dòng)態(tài)生成,并且只更新那些改變過(guò)的字段。 8、 dynamic-insert(動(dòng)態(tài)插入) (可選, 默認(rèn)為false): 指定用于INSERT的 SQL 將會(huì)在運(yùn)行時(shí)動(dòng)態(tài)生成,并且只包含那些非空值字段。 9、 select-before-update (可選,默認(rèn)值為false): 指定Hibernate除非確定對(duì)象的確被修改了,不會(huì)執(zhí)行SQL UPDATE操作。在特定場(chǎng)合(實(shí)際上,只會(huì)發(fā)生在一個(gè)臨時(shí)對(duì)象關(guān)聯(lián)到一個(gè)新的session中去,執(zhí)行update()的時(shí)候),這說(shuō)明Hibernate會(huì)在UPDATE之前執(zhí)行一次額外的SQL SELECT操作,來(lái)決定是否應(yīng)該進(jìn)行UPDATE。 10、 polymorphism(多形,多態(tài)) (可選, 默認(rèn)值為 implicit (隱式): 界定是隱式還是顯式的使用查詢(xún)多態(tài)。 11、 where (可選) 指定一個(gè)附加的SQLWHERE 條件,在抓取這個(gè)類(lèi)的對(duì)象時(shí)會(huì)一直增加這個(gè)條件。 12、 persister (可選): 指定一個(gè)定制的ClassPersister。 13、 batch-size (可選,默認(rèn)是1) 指定一個(gè)用于根據(jù)標(biāo)識(shí)符抓取實(shí)例時(shí)使用的batch size(批次抓取數(shù)量)。 14、 optimistic-lock(樂(lè)觀鎖定) (可選,默認(rèn)是version): 決定樂(lè)觀鎖定的策略。 15、 lazy(延遲) (可選): 假若設(shè)置 lazy=true,就是設(shè)置這個(gè)類(lèi)自己的名字作為proxy接口的一種等價(jià)快捷形式。四、id持久化類(lèi)必須要聲明一個(gè)字段對(duì)應(yīng)數(shù)據(jù)庫(kù)表的主鍵。 (5) (1)、name(可選):標(biāo)識(shí)屬性的名稱(chēng)。(2)、type(可選):標(biāo)識(shí)Hibernate類(lèi)型的名字。(3)、column(可選默認(rèn)為屬性名):對(duì)應(yīng)數(shù)據(jù)庫(kù)表的主鍵字段的名字。(4)、unsaved-value(可選默認(rèn)為null):這個(gè)值用來(lái)判斷對(duì)象是否要保存。如果一個(gè)對(duì)象id值與該值相等時(shí),Hibernate則會(huì)認(rèn)為該對(duì)象是一個(gè)新的對(duì)象,并沒(méi)有持據(jù)化到數(shù)據(jù)庫(kù)中。舉例:假如一個(gè)新建對(duì)象的屬性id的類(lèi)型為int,我們知道如果不給id賦值,它默認(rèn)的值就應(yīng)該是“0”,如果這時(shí)unsaved-value是默認(rèn)的null。則當(dāng)保存這個(gè)新建對(duì)象,調(diào)用session. SaveOrUpdate()方法時(shí)會(huì)拋出異常。因?yàn)閕d的值不等于null,所以Hibernate會(huì)認(rèn)為該對(duì)象已經(jīng)保存,它會(huì)去執(zhí)行update操作。Generator主鍵生成器,每個(gè)主鍵都必須定義相應(yīng)的主鍵生成策略。它用來(lái)為持久化類(lèi)實(shí)例生成唯一的標(biāo)識(shí)。例如: uid_table next_hi_value_column 所有的生成器都實(shí)現(xiàn)net.sf.hibernate.id.IdentifierGenerator接口。這是一個(gè)非常簡(jiǎn)單的接口;某些應(yīng)用程序可以選擇提供他們自己特定的實(shí)現(xiàn)。當(dāng)然,Hibernate提供了很多內(nèi)置的實(shí)現(xiàn)。下面是一些內(nèi)置生成器的快捷名字:1、 數(shù)據(jù)庫(kù)提供的主鍵生成機(jī)制。identity、sequence、2、 外部程序提供的主鍵生成機(jī)制。increment ,hilo,seqhilo,uuid.hex,uuid.string3、 其它。native,assigned,foreignincrement(遞增):主鍵按數(shù)值順序遞增。此方式的實(shí)現(xiàn)機(jī)制為在當(dāng)前應(yīng)用實(shí)例中維持一個(gè)變量,以保存著當(dāng)前的最大值,之后每次需要生成主鍵的時(shí)候?qū)⒋酥导?作為主鍵。用于為long, short或者int類(lèi)型生成唯一標(biāo)識(shí)。只有在沒(méi)有其他進(jìn)程往同一張表中插入數(shù)據(jù)時(shí)才能使用。 在集群下不要使用。identity采用數(shù)據(jù)庫(kù)提供的主鍵生成機(jī)制(數(shù)據(jù)庫(kù)內(nèi)部支持標(biāo)識(shí)字段)。如DB2、SQL Server、MySQL中的主鍵生成機(jī)制。返回的標(biāo)識(shí)符是long, short 或者int類(lèi)型的。sequence (序列):采用數(shù)據(jù)庫(kù)提供的sequence 機(jī)制生成主鍵。如Oralce 中的Sequence。hilo (高低位): 通過(guò)hi/lo算法實(shí)現(xiàn)的主鍵生成機(jī)制,需要額外的數(shù)據(jù)庫(kù)表保存主鍵生成歷史狀態(tài)。高/低位算法生成的標(biāo)識(shí)符只在一個(gè)特定的數(shù)據(jù)庫(kù)中是唯一的。在使用JTA獲得的連接或者用戶(hù)自行提供的連接中,不要使用這種生成器。seqhilo(使用序列的高低位):與hilo 類(lèi)似,通過(guò)hi/lo 算法實(shí)現(xiàn)的主鍵生成機(jī)制,只是主鍵歷史狀態(tài)保存在Sequence中,適用于支持Sequence的數(shù)據(jù)庫(kù),如Oracle。uuid.hex用一個(gè)128-bit的UUID算法生成字符串類(lèi)型的標(biāo)識(shí)符。在一個(gè)網(wǎng)絡(luò)中唯一(使用了IP地址,JVM的啟動(dòng)時(shí)間(精確到1/4秒),系統(tǒng)時(shí)間和一個(gè)計(jì)數(shù)器值(在JVM中唯一)。)。UUID被編碼為一個(gè)32位16進(jìn)制數(shù)字的字符串。uuid.string使用同樣的UUID算法。UUID被編碼為一個(gè)16個(gè)字符長(zhǎng)的任意ASCII字符組成的字符串native(本地)根據(jù)底層數(shù)據(jù)庫(kù)的能力選擇identity, sequence 或者h(yuǎn)ilo中的一個(gè)assigned(程序設(shè)置)讓?xiě)?yīng)用程序在save()之前為對(duì)象分配一個(gè)標(biāo)示符。foreign(外部引用)使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的標(biāo)識(shí)符。和聯(lián)合一起使用。五:property元素為類(lèi)聲明了一個(gè)持久化的,JavaBean風(fēng)格的屬性。 (1) name: 屬性的名字,以小寫(xiě)字母開(kāi)頭。 (2) column (可選 - 默認(rèn)為屬性名字): 對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段名。 (3) type (可選): 一個(gè)Hibernate類(lèi)型的名字。 (4) update, insert (可選 - 默認(rèn)為 true) :表明在用于UPDATE 和/或 INSERT的SQL語(yǔ)句中是否包含這個(gè)字段。這二者如果都設(shè)置為false則表明這是一個(gè)“外源性(derived)”的屬性,它的值來(lái)源于映射到同一個(gè)(或多個(gè))字段的某些其他屬性,或者通過(guò)一個(gè)trigger(觸發(fā)器),或者其他程序。 (5) formula (可選): 一個(gè)SQL表達(dá)式,定義了這個(gè)計(jì)算(computed) 屬性的值。計(jì)算屬性沒(méi)有和它對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段。 (6) access (可選 - 默認(rèn)值為 property): Hibernate用來(lái)訪問(wèn)屬性值的策略。六、多對(duì)一個(gè)(many-to-one)(1) name: 屬性名。 (2) column (可選): 字段名。 (3) class (可選 - 默認(rèn)是通過(guò)反射得到屬性類(lèi)型): 關(guān)聯(lián)的類(lèi)的名字。 (4) cascade(級(jí)聯(lián)) (可選): 指明哪些操作會(huì)從父對(duì)象級(jí)聯(lián)到關(guān)聯(lián)的對(duì)象。 (5) outer-join(外連接) (可選 - 默認(rèn)為 自動(dòng)): 當(dāng)設(shè)置hibernate.use_outer_join的時(shí)候,對(duì)這個(gè)關(guān)聯(lián)允許外連接抓取。 (6) update, insert (可選 - defaults to true) 指定對(duì)應(yīng)的字段是否在用于UPDATE 和/或 INSERT的SQL語(yǔ)句中包含。如果二者都是false,則這是一個(gè)純粹的“外源性(derived)”關(guān)聯(lián),它的值是通過(guò)映射到同一個(gè)(或多個(gè))字段的某些其他屬性得到的,或者通過(guò)trigger(觸發(fā)器),或者是其他程序。 (7) property-ref: (可選) 指定關(guān)聯(lián)類(lèi)的一個(gè)屬性,這個(gè)屬性將會(huì)和本外鍵相對(duì)應(yīng)。如果沒(méi)有指定,會(huì)使用對(duì)方關(guān)聯(lián)類(lèi)的主鍵。 該屬性只應(yīng)該用來(lái)對(duì)付老舊的數(shù)據(jù)庫(kù)系統(tǒng),可能出現(xiàn)外鍵指向?qū)Ψ疥P(guān)聯(lián)表的是個(gè)非主鍵字段(但是應(yīng)該是一個(gè)惟一關(guān)鍵字)的情況。(8) access (可選 - 默認(rèn)是 property): Hibernate用來(lái)訪問(wèn)屬性的策略。七、一對(duì)多(one-to-many)(1) name 集合屬性的名稱(chēng) (2) table (可選)目標(biāo)關(guān)聯(lián)數(shù)據(jù)庫(kù)表(3) lazy (可選默認(rèn)為false)允許延遲加載(lazy initialization )(4) inverse (可選默認(rèn)為false) 標(biāo)記這個(gè)集合作為雙向關(guān)聯(lián)關(guān)系中的方向一端。 (5) cascade (可選默認(rèn)為none) 讓操作級(jí)聯(lián)到子實(shí)體 (6) sort(可選默認(rèn)為unsorted)指定集合的排序順序, 其可以為自然的(natural)或者給定一個(gè)用來(lái)比較的類(lèi)。 (7) order-by (可選, 僅用于jdk1.4) 指定表的字段(一個(gè)或幾個(gè))再加上asc或者desc(可選), 定義Map,Set和Bag的迭代順序 (8) where (可選) 指定任意的SQL where條件。該條件將在重新載入或者刪除這個(gè)集合時(shí)使用(當(dāng)集合中的數(shù)據(jù)僅僅是所有可用數(shù)據(jù)的一個(gè)子集時(shí)這個(gè)條件非常有用)(9) outer-join(可選-默認(rèn)為a
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 一站式購(gòu)物中心樓層委托管理服務(wù)協(xié)議
- 區(qū)塊鏈服務(wù)器托管與數(shù)據(jù)加密服務(wù)協(xié)議
- 工業(yè)液壓系統(tǒng)濾芯租賃與智能檢測(cè)合同
- 同聲傳譯翻譯服務(wù)項(xiàng)目變更補(bǔ)充合同
- 國(guó)際會(huì)議同傳耳機(jī)消毒租賃與現(xiàn)場(chǎng)翻譯支持服務(wù)協(xié)議
- 智能家居生態(tài)鏈建設(shè)與合作知識(shí)產(chǎn)權(quán)保護(hù)協(xié)議
- 醫(yī)療器械臨床試驗(yàn)項(xiàng)目風(fēng)險(xiǎn)管理與應(yīng)對(duì)協(xié)議
- 虛擬現(xiàn)實(shí)影視預(yù)演系統(tǒng)租賃與服裝租賃協(xié)議
- DB42-T 2037.1-2023 梨形環(huán)棱螺養(yǎng)殖技術(shù)規(guī)程 第1部分:苗種繁育
- “然”用法總結(jié)模版
- 荷蘭語(yǔ)常用詞匯
- 移動(dòng)通信原理和系統(tǒng)習(xí)題答案
- 《動(dòng)畫(huà)素描》第一章 動(dòng)畫(huà)素描概述
- 無(wú)軌膠輪車(chē)運(yùn)行標(biāo)準(zhǔn)作業(yè)流程
- GB/T 12513-2006鑲玻璃構(gòu)件耐火試驗(yàn)方法
- 公路工程施工現(xiàn)場(chǎng)安全檢查手冊(cè)
- 部編版小學(xué)語(yǔ)文六年級(jí)下冊(cè)《采薇》課件(完美)
- 激光跟蹤儀使用手冊(cè)
- 馬家河金礦選礦試驗(yàn)報(bào)告
- “新時(shí)代好少年”推薦表
- 園林綠化工程監(jiān)理實(shí)施細(xì)則(完整版)
評(píng)論
0/150
提交評(píng)論