版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、Good is good, but better carries it.精益求精,善益求善。Hibernate教程講師用-Hibernate教程前言java對象持久化技術1.1、hibernate是什么1.2、軟件模型1.2.1、概念模型1.2.2、關系數(shù)據(jù)模型1.2.3、域模型1.2.4、域對象1.2.5、域對象之間的關系1.2.6、域對象的持久化概念提示:1.3、數(shù)據(jù)庫訪問模式1.3.1、ORM模式1.3.2、主動域對象模式1.3.3、JDO模式1.3.4、CMP模式一、數(shù)據(jù)源層O/RMapping主要介紹三層架構,如何分層?(邏輯上的分層,二個原則)數(shù)據(jù)層技術的選擇:直接使用1.1、SQ
2、L/JDBC:優(yōu)點:很多開發(fā)者熟悉關系數(shù)據(jù)庫管理系統(tǒng),理解SQL,也知道如何使用表和外鍵進行工作。此外,他們可以始終使用眾所周知并廣泛使用的DAO設計模式對業(yè)務邏輯隱藏復雜的JDBC代碼和不可移植的SQL。缺點:為域中的每個類手工編寫持續(xù)性代碼的工作是非??捎^的,特別是需要支持多種SQL方言時。這項工作通常會消耗很大一部分的開發(fā)努力。此外,當需求改變時,一個手工編碼的解決方案總是需要更多的注意和維護努力。1.2、序列化:Java有一個內(nèi)建的持久化機制:序列化提供了將對象圖(應用狀態(tài))寫到字節(jié)流中的能力,然后它可能被持久化到文件或數(shù)據(jù)庫中。持久化也被Java的遠程方法調(diào)用(RMI)使用來為復雜對
3、象傳遞值語義。持久化的另一種用法是在機器集群中跨節(jié)點復制應用狀態(tài)。缺點:很不幸,一個相互連接的對象圖在序列化之后只能被當作一個整體訪問,如果不反序列化整個流就不可能從流中取出任何數(shù)據(jù)。這樣,結果字節(jié)流肯定會被認為不適合進行任意的檢索或聚合。甚至不可能獨立地訪問或更新一個單獨的對象或子圖。非常明顯,因為當前特定的技術,序列化不適合于作為高并發(fā)性的Web和企業(yè)應用的持久化機制。在特定的環(huán)境中它被作為桌面應用的適當?shù)某志没瘷C制。1.3EJBentitybeansEJB1.1實體Bean在實踐中徹底地失敗了。EJB規(guī)范的設計缺陷阻礙了Bean管理的持續(xù)性(BMP)實體Bean有效地執(zhí)行。在EJB1.1
4、許多明顯的缺陷被糾正之后,一個邊緣的稍微可接受的解決方案是容器管理的持續(xù)性(CMP)。然而,CMP并不能表示一種對象-關系不匹配的解決方案。CMP缺點:CMP實體Bean的粒度既太粗又太細:CMPBean與關系模型中的表是按照一對一的方式定義的。這樣,它們的粒度過粗,不能夠完全利用Java豐富的類型。雖然EJB可以利用繼承實現(xiàn),但實體Bean并不支持多態(tài)的關聯(lián)和查詢不管EJB規(guī)范所宣稱的目標,實體Bean實際上是不可移植的。CMP引擎的性能因廠商而異,并且映射元數(shù)據(jù)也是高度特定于廠商的。實體Bean不可序列化。我們發(fā)現(xiàn)當我們需要將數(shù)據(jù)傳輸?shù)竭h程客戶層時,我們必須定義額外的數(shù)據(jù)傳輸對象(DTO,
5、也被稱作值對象)實體Bean必須依賴于EJB容器測試困難。JDO、Object-orienteddatabasesystems大多數(shù)面向對象的數(shù)據(jù)庫系統(tǒng)對ODMG標準都提供了許多程度的支持,但據(jù)我們所知,還沒有完全的實現(xiàn)。此外,在規(guī)范發(fā)布以后的很多年,甚至到了3.0版,還是感覺不太成熟,并且缺乏很多有用的特征,特別是基于Java環(huán)境的。ODMG也不再活躍。最近,Java數(shù)據(jù)對象(JDO)規(guī)范(發(fā)表于2002年4月)揭開了新的可能性。JDO由面向對象數(shù)據(jù)庫團體的成員驅動,除了對現(xiàn)有的ODMG的支持之外,面向對象的數(shù)據(jù)庫產(chǎn)品現(xiàn)在還經(jīng)常將其作為主要的API采用。JDO的優(yōu)點在于它很簡單。開發(fā)人員使用
6、Java語言持久存儲對象實例并從存儲器檢索實例。處理邏輯、同步和故障轉移等均被透明地處理。開發(fā)人員無需使用SQL或Java語言提供的不便的序列化機制,只使用POJO(無格式普通Java對象)即可,利用JDO接口將對象引用傳遞到存儲器中并從存儲器檢索對象引用。1.4、O/RMapping1.4.1什么是O/RMapping?它有什么優(yōu)點?簡單地說,對象-關系映射就是Java應用中的對象到關系數(shù)據(jù)庫中的表的自動的(和透明的)持久化,使用元數(shù)據(jù)(metadata)描述對象與數(shù)據(jù)庫間的映射。本質上,ORM的工作是將數(shù)據(jù)從一種表示(雙向)轉換為另一種。提高生產(chǎn)率(Productivity)與持久性有關的
7、代碼可能是Java應用中最乏味的代碼。Hibernate去掉了很多讓人心煩的工作(多于你的期望),讓你可以集中更多的精力到業(yè)務問題上。不論你喜歡哪種應用開發(fā)策略自頂向下,從域模型開始;或者自底向上,從一個現(xiàn)有的數(shù)據(jù)庫模式開始使用Hibernate和適當?shù)墓ぞ邔p少大量的開發(fā)時間。可維護性(Maintainability)減少了代碼,重構更方便,提高了可維護性。ORM是對象和關系數(shù)據(jù)庫之間的緩沖區(qū),用來很好的將他們隔離。更好性能(Performance)ORM軟件的實現(xiàn)人員可能有比你更多的時間來研究性能優(yōu)化問題。你知道嗎,例如,緩存PreparedStatement的實例對DB2的JDBC驅動
8、導致了一個明顯的性能增長但卻破壞了InterBase的JDBC驅動?你了解嗎,對某些數(shù)據(jù)庫只更新一個表中被改變的字段可能會非常快但潛在地對其它的卻很慢?在你手工編寫的解決方案中,對這些不同策略之間的沖突進行試驗是多么不容易呀?廠商獨立性(Vendorindependence)ORM抽象了你的應用使用下層SQL數(shù)據(jù)庫和SQL方言的方式。如果工具支持許多不同的數(shù)據(jù)庫(dialect),那么這會給你的應用帶來一定程度的可移植性。你不必期望可以達到“一次編寫,到處運行”,因為數(shù)據(jù)庫的性能不同并且達到完全的可移植性需要犧牲更強大的平臺的更多的力氣。然而,使用ORM開發(fā)跨平臺的應用通常更容易。即使你不需要
9、跨平臺操作,ORM依然可以幫你減小被廠商鎖定的風險。另外,數(shù)據(jù)庫獨立性對這種開發(fā)情景也有幫助:開發(fā)者使用一個輕量級的本地數(shù)據(jù)庫進行開發(fā)但實際產(chǎn)品需要配置在一臺不同的數(shù)據(jù)庫上。1.5對象關系的不匹配范式(paradigm)1.5.1粒度(granularity)的問題。增加一種新的數(shù)據(jù)類型,將Java地址對象在我們的數(shù)據(jù)庫中保存為單獨的一列,聽起來好像是最好的方法。畢竟,Java中的一個新的地址類與SQL數(shù)據(jù)類型中的一個新的地址類型可以保證互用性。然而,如果你檢查現(xiàn)在的數(shù)據(jù)庫管理系統(tǒng)對用戶定義列類型(UDT)的支持,你將會發(fā)現(xiàn)各種各樣的問題。子類型(subtypes)的問題。子類型不匹配是指Ja
10、va模型中的繼承結構必須被持續(xù)化到SQL數(shù)據(jù)庫中,而SQL數(shù)據(jù)庫并沒有提供一個支持繼承的策略。如何解決多態(tài)?同一性(identity)的問題Java對象定義了兩種不同的相等性的概念:對象同一性(粗略的等同于內(nèi)存位置的相等,使用a=b檢查)通過equals()方法的實現(xiàn)來決定的相等性(也被稱作值相等)另一方面,數(shù)據(jù)庫行的同一性使用主鍵值表示。主鍵既不必然地等同于“equals()”也不等同于“=”。它通常是指幾個對象(不相同的)同時表示了數(shù)據(jù)庫中相同的行。而且,為一個持續(xù)類正確地實現(xiàn)equals()方法包含許多微妙的難點。與關聯(lián)(associations)有關的問題面向對象的語言使用對象引用和對
11、象引用的集合表示關聯(lián)。在關系世界里,關聯(lián)被表示為外鍵列,外鍵是幾個表的鍵值的拷貝。這兩種表示之間有些微妙的不同。對象結構導航的問題在Java中訪問對象的方式與在關系數(shù)據(jù)庫中有根本的不同。在Java中,訪問用戶的賬單信息時,你調(diào)用aUser.getBillingDetails().getAccountNumber()。這是最自然的面向對象數(shù)據(jù)的訪問方式,通常被形容為遍歷對象圖。根據(jù)實例間的關聯(lián),你從一個對象導航到另一個對象。不幸地是,這不是從SQL數(shù)據(jù)庫中取出數(shù)據(jù)的有效方式。為了提高數(shù)據(jù)訪問代碼的性能,唯一重要的事是最小化數(shù)據(jù)庫請求的次數(shù)。最明顯的方式是最小化SQL查詢的數(shù)量(其它方式包括使用存
12、儲過程或者JDBC批處理API)。使用SQL有效地訪問關系數(shù)據(jù)通常需要在有關的表之間使用連接。在連接中包含的表的數(shù)量決定了你可以導航的對象圖的深度。性能:N+1的問題范式不匹配的代價:1、花費很多時間和精力來手工解決對象和關系的不匹配。2、為了解決不匹配,甚至要扭曲對象模型直到它與下層的關系技術匹配為止JDBCAPI本身的問題。JDBC和SQL提供了一個面向語句(即命令)的方法從SQL數(shù)據(jù)庫中來回移動數(shù)據(jù)。至少在三個時刻(Insert,Update,Select)必須指定一個結構化關系,這增加了設計和實現(xiàn)所需要的時間。1.6、主流持久層框架縱覽目前眾多廠商和開源社區(qū)都提供了持久層框架實現(xiàn),常見
13、的有:ApacheOJB(/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)品。其他均為開源項目)1.6.1ApacheOJB它的優(yōu)勢在于對各種標準的全面支持(不過事實上,我們的系統(tǒng)研發(fā)中并不需要同時支持這么多標準,追求多種標準的并行支持本身也成為ApacheO
14、JB項目發(fā)展的沉重包袱),且其從屬于Apache基金組織,有著可靠的質量保證和穩(wěn)定的發(fā)展平臺。1.6.2Hibernate在2003年末被JBoss組織收納,成為從屬于JBoss組織的子項目之一,從而贏得了良好的發(fā)展前景(同時榮獲Jolt2004大獎)。Hibernate與OJB設計思想類似,具備相近的功能和特色,但由于其更加靈活快速的發(fā)展策略,得到了廣大技術人員的熱情參與,因此也得到了更廣泛的推崇。相對ApacheOJB遲鈍的項目開發(fā)進度表,Hibernate活躍的開發(fā)團隊以及各社區(qū)內(nèi)對其熱烈的關注為其帶來了極大的活力,并逐漸發(fā)展成Java持久層事實上的標準。1.6.3iBATIS相對Apa
15、cheOJB和Hibernate項目則另具特色,iBATIS采取了更加開放式的設計,通過iBATIS,我們可以控制更多的數(shù)據(jù)庫操作細節(jié)。相對而言,Hibernate、ApacheOJB對持久層的設計則較為封閉,封閉化的設計對持久層進行了較為徹底的封裝,從而將底層細節(jié)與上層架構完全分離,大多數(shù)情況下,特別是對于新系統(tǒng),新產(chǎn)品的研發(fā)而言,封閉化的設計帶來了更高的開發(fā)效率和更好的封裝機制,但是在某些情況下,卻又為一些必須的底層調(diào)整帶來了阻力,如在對遺留系統(tǒng)的改造和對既有數(shù)據(jù)庫的復用上,表現(xiàn)出靈活性不足的弱點。此時作為OJB,Hibernate的一個有益補充,iBATIS的出現(xiàn)顯得別具意義。二、Hib
16、ernate入門2.1、Hibernate概述Hibernate是非常優(yōu)秀、成熟的O/RMapping框架。它提供了強大、高性能的Java對象和關系數(shù)據(jù)的持久化和查詢功能。(O/RMapping是一項實用的工程技術,把數(shù)據(jù)庫的E/R模型用java的OO語法描述出來,Hibernate是其中的當之無愧的最耀眼的明星,cglib動態(tài)增強,多種靈活的class繼承樹映射機制,廣泛的社團支援,掩蓋了其他項目的光輝。)2.2、Hibernate的優(yōu)勢開源(LGPL)成熟流行(約13000downloads/month)自定義APIJBoss將用Hibernate3實現(xiàn)EntityBeans2.3、使用H
17、ibernate的開發(fā)步驟設計一般首先進行領域對象的設計。因為在Hibernate中,我們的領域對象可以直接充當持久化類。映射定義Hibernate的映射文件,實現(xiàn)持久化類和數(shù)據(jù)庫之間映射。應用使用Hibernate提供的API,實現(xiàn)具體的持久化業(yè)務。2.4、Hibernate的映射Entity-hbm-ddl(數(shù)據(jù)庫)(hbm(hibernatemapping)和ddl(DataDefinitionLanguage)的全稱)之間的互相轉換User.javaUser.hbm.xmlXDoclet:它通過在Java源代碼中加入特定的JavaDoctag,從而為其添加特定的附加語義,之后通過XDo
18、clet工具對代碼中JavaDocTag進行分析,自動生成與代碼對應的配置文件(/)。XDoclet提供了對Hibernate的支持,這樣我們可以直接由Java代碼生成Hibernate映射文件。Middlegen:用來從數(shù)據(jù)庫中已有的表結構中生成Hibernate映射文件。當前版本是2.1可以去HYPERLINKhttp:/boss.bekk.no/boss/middlegenhttp:/boss.bekk.no/boss/middlegen下載。2.5、Hibernate核心接口2.5.1、Configuration:正如其名,Configuration類負責管理Hibernate的配置信
19、息。Hibernate運行時需要獲取一些底層實現(xiàn)的基本信息,其中幾個關鍵屬性包括:1、數(shù)據(jù)庫URL2、數(shù)據(jù)庫用戶3、數(shù)據(jù)庫用戶密碼4、數(shù)據(jù)庫JDBC驅動類5、數(shù)據(jù)庫dialect(方言),用于對特定數(shù)據(jù)庫提供支持,其中包含了針對特定數(shù)據(jù)庫特性的實現(xiàn),如Hibernate數(shù)據(jù)類型到特定數(shù)據(jù)庫數(shù)據(jù)類型的映射等。6、當然,還有指定Hibernate映射文件的位置。(*.hbm.xml)。Hibernate配置有兩種方法:屬性文件配置。默認文件名是perties。調(diào)用代碼:Configurationconfig=newConfiguration();XML文件配置。默認文件名是hibernate.cf
20、g.xml。Configurationconfig=newConfiguration().configure();2.5.2、SessionFactory:應用程序從SessionFactory(會話工廠)里獲得Session(會話)實例。它打算在多個應用線程間進行共享。通常情況下,整個應用只有唯一的一個會話工廠例如在應用初始化時被創(chuàng)建。然而,如果你使用Hibernate訪問多個數(shù)據(jù)庫,你需要對每一個數(shù)據(jù)庫使用一個會話工廠。會話工廠緩存了生成的SQL語句和Hibernate在運行時使用的映射元數(shù)據(jù)。它也保存了在一個工作單元中讀入的數(shù)據(jù)并且可能在以后的工作單元中被重用(只有類和集合映射指定了使用
21、這種二級緩存時才會如此)。SessionFactorysessionFactory=config.buildSessionFactory();2.5.3、Session(會話):該接口是Hibernate使用最多的接口。Session不是線程安全的,它代表與數(shù)據(jù)庫之間的一次操作。Session通過SessionFactory打開,在所有的工作完成后,需要關閉:它的概念介于Connection和Transaction之間。我們可以簡單的認為它是已經(jīng)裝載對象的緩存或集合的一個獨立工作單元。我們有時也稱Session為持久化管理器,因為它是與持久化有關的操作的接口。Hibernate會話并不是線程安
22、全的因此應該被設計為每次只能在一個線程中使用。Hibernate會話與Web層的HttpSession沒有任何關系。Sessionsession=sessionFactory.openSession();2.5.4、Transaction:事務將應用代碼從底層的事務實現(xiàn)中抽象出來這可能是一個JDBC事務,一個JTA用戶事務或者甚至是一個公共對象請求代理結構(CORBA)允許應用通過一組一致的API控制事務邊界。這有助于保持Hibernate應用在不同類型的執(zhí)行環(huán)境或容器中的可移植性。Transactiontrans=session.beginTransaction();2.5.5、Query:
23、Query(查詢)接口允許你在數(shù)據(jù)庫上執(zhí)行查詢并控制查詢?nèi)绾螆?zhí)行。查詢語句使用HQL或者本地數(shù)據(jù)庫的SQL方言編寫。Queryquery=session.createQuery(“fromUser”);2.5.6、Lifecycle:Lifecycle接口提供了一些回調(diào)方法,可以讓持久化對象在save或load之后,或者在delete或update之前進行必要的初始化與清除步驟。publicinterfaceLifecyclepublicbooleanonSave(Sessions)throwsCallbackException;(1)publicbooleanonUpdate(Session
24、s)throwsCallbackException;(2)publicbooleanonDelete(Sessions)throwsCallbackException;(3)publicvoidonLoad(Sessions,Serializableid);(4)(1)onSave-在對象即將被save或者insert的時候回調(diào)(2)onUpdate-在對象即將被update的時候回調(diào)(也就是對象被傳遞給Session.update()的時候)(3)onDelete-在對象即將被delete(刪除)的時候回調(diào)(4)onLoad-在對象剛剛被load(裝載)后的時候回調(diào)2.5.6、Validat
25、able:該接口是合法性檢查的回調(diào)。如果持久化類需要在保存其持久化狀態(tài)前進行合法性檢查,它可以實現(xiàn)下面的接口:publicinterfaceValidatablepublicvoidvalidate()throwsValidationFailure;如果發(fā)現(xiàn)對象違反了某條規(guī)則,應該拋出一個ValidationFailure異常。在Validatable實例的validate()方法內(nèi)部不應該改變它的狀態(tài)。和Lifecycle接口的回調(diào)方法不同,validate()可能在任何時間被調(diào)用。應用程序不應該把validate()調(diào)用和商業(yè)功能聯(lián)系起來。2.5.7、Interceptor:Interce
26、ptor接口提供從session到你的應用程序的回調(diào)方法,讓你的程序可以觀察和在持久化對象保存/更改/刪除或者裝載的時候操作它的屬性。一種可能的用途是用來監(jiān)視統(tǒng)計信息。2.5.8、UserType:開發(fā)者創(chuàng)建屬于他們自己的值類型也是很容易的。比如說,你可能希望持久化java.lang.BigInteger類型的屬性,持久化成為VARCHAR字段。Hibernate沒有內(nèi)置這樣一種類型。自定義類型能夠映射一個屬性(或集合元素)到不止一個數(shù)據(jù)庫表字段。比如說,你可能有這樣的Java屬性:getName()/setName(),這是java.lang.String類型的,對應的持久化到三個字段:FI
27、RST_NAME,INITIAL,SURNAME。要實現(xiàn)一個自定義類型,可以實現(xiàn)net.sf.hibernate.UserType或net.sf.hibernate.CompositeUserType中的任一個,并且使用類型的Java全限定類名來聲明屬性。請查看net.sf.hibernate.test.DoubleStringType這個例子,看看它是怎么做的。注意使用標簽來把一個屬性映射到多個字段的做法。2.6、持久化類(PersistentClass)持久化類不需要實現(xiàn)什么特別的接口,也不需要從一個特別的持久化根類繼承下來。Hibernate也不需要使用任何編譯期處理,比如字節(jié)碼增強操作
28、,它獨立的使用Java反射機制和運行時類增強(通過CGLIB)。所以,在Hibernate中,POJO的類不需要任何前提條件,我們就可以把它映射成為數(shù)據(jù)庫表。持久化類必須遵循的原則:為類的持久化類字段申明訪問方法(Get/set)。Hibernate對JavaBeans風格的屬性實行持久化。實現(xiàn)一個默認的構造方法(constructor)。這樣的話Hibernate就可以使用Constructor.newInstance()來實例化它們。如果是集合類型的屬性,它的類型必須定義為集合的接口。例如:List、Set提供一個標識屬性(identifierproperty)。如果沒有該屬性,一些功能不
29、起作用,比如:級聯(lián)更新(Cascadedupdates)Session.saveOrUpdate()。三、Hibernate映射聲明(Mappingdeclaration)3.1、DOCTYPE聲明。一個XMLdocument應該在文檔的起始位置有一個XML的聲明,可能跟隨著一個DOCTYPE的聲明。一個DOCTYPE聲明告訴一個XMLparser這個XML文檔遵循了哪一個DTD(DocumentTypeDeclaration)。Parser可以用此信息來確認這個XML文檔包含的僅是這個DTD聲明的XMLelement。例如:DTD可以從上述URL中獲取,或者在hibernate-x.x.x/
30、src/net/sf/hibernate目錄中,或hibernate.jar文件中找到。Hibernate總是會在它的classptah中首先搜索DTD文件。3.2、hibernate-mapping它是文檔的根(root),可以包含多個類的映射,但一般只包含一個類。(1)、schema(可選):數(shù)據(jù)庫SchemaName(2)、default-cascade(可選,默認為none):默認的級聯(lián)風格(3)、auto-import(可選,默認為true):是否允許在查詢語言中使用非完全限定的類名即只用類的名稱,不用加入包名(僅限本映射文件中定義的類)。(4)、package(可選),如果該映射文
31、件中定義的類名不包含package,則使用這里定義的package作為類名的前綴。注:(3)默認的值是“true”,如果有多個類的名字相同,則必須將該值設為false。3.2、class用class元素來定義一個持久化類。name:持久化類(或Java接口)的全名。table:對應的數(shù)據(jù)庫表名。discriminator-value(鑒別值)(可選,默認和類名一樣):一個用于區(qū)分不同子類的值,在多態(tài)行為中使用。mutable(可選,默認值為true):表明該類是否可以改變。如果將它設為false,則應用程序不能對此類對應的數(shù)據(jù)進行修改和刪除。schema(可選):覆蓋在根元素中指定的schem
32、a名字。proxy(可選):指定一個接口,在延遲裝載時作為代理使用。你可以在這里使用該類自己的名字。dynamic-update(動態(tài)更新)(可選,默認為false):指定用于UPDATE的SQL將會在運行時動態(tài)生成,并且只更新那些改變過的字段。dynamic-insert(動態(tài)插入)(可選,默認為false):指定用于INSERT的SQL將會在運行時動態(tài)生成,并且只包含那些非空值字段。select-before-update(可選,默認值為false):指定Hibernate除非確定對象的確被修改了,不會執(zhí)行SQLUPDATE操作。在特定場合(實際上,只會發(fā)生在一個臨時對象關聯(lián)到一個新的se
33、ssion中去,執(zhí)行update()的時候),這說明Hibernate會在UPDATE之前執(zhí)行一次額外的SQLSELECT操作,來決定是否應該進行UPDATE。polymorphism(多形,多態(tài))(可選,默認值為implicit(隱式):界定是隱式還是顯式的使用查詢多態(tài)。where(可選)指定一個附加的SQLWHERE條件,在抓取這個類的對象時會一直增加這個條件。persister(可選):指定一個定制的ClassPersister。batch-size(可選,默認是1)指定一個用于根據(jù)標識符抓取實例時使用的batchsize(批次抓取數(shù)量)。optimistic-lock(樂觀鎖定)(可選
34、,默認是version):決定樂觀鎖定的策略。lazy(延遲)(可選):假若設置lazy=true,就是設置這個類自己的名字作為proxy接口的一種等價快捷形式。3.3、id持久化類必須要聲明一個字段對應數(shù)據(jù)庫表的主鍵。(5)(1)、name(可選):標識屬性的名稱。(2)、type(可選):標識Hibernate類型的名字。(3)、column(可選默認為屬性名):對應數(shù)據(jù)庫表的主鍵字段的名字。(4)、unsaved-value(可選默認為null):這個值用來判斷對象是否要保存。如果一個對象id值與該值相等時,Hibernate則會認為該對象是一個新的對象,并沒有持據(jù)化到數(shù)據(jù)庫中。舉例:假
35、如一個新建對象的屬性id的類型為int,我們知道如果不給id賦值,它默認的值就應該是“0”,如果這時unsaved-value是默認的null。則當保存這個新建對象,調(diào)用session.SaveOrUpdate()方法時會拋出異常。因為id的值不等于null,所以Hibernate會認為該對象已經(jīng)保存,它會去執(zhí)行update操作。Generator主鍵生成器,每個主鍵都必須定義相應的主鍵生成策略。它用來為持久化類實例生成唯一的標識。例如:uid_tablenext_hi_value_column所有的生成器都實現(xiàn)net.sf.hibernate.id.IdentifierGenerator接口
36、。這是一個非常簡單的接口;某些應用程序可以選擇提供他們自己特定的實現(xiàn)。當然,Hibernate提供了很多內(nèi)置的實現(xiàn)。下面是一些內(nèi)置生成器的快捷名字:數(shù)據(jù)庫提供的主鍵生成機制。identity、sequence、外部程序提供的主鍵生成機制。increment,hilo,seqhilo,uuid.hex,uuid.string其它。native,assigned,foreignincrement(遞增):主鍵按數(shù)值順序遞增。此方式的實現(xiàn)機制為在當前應用實例中維持一個變量,以保存著當前的最大值,之后每次需要生成主鍵的時候將此值加1作為主鍵。用于為long,short或者int類型生成唯一標識。只有在
37、沒有其他進程往同一張表中插入數(shù)據(jù)時才能使用。在集群下不要使用。identity采用數(shù)據(jù)庫提供的主鍵生成機制(數(shù)據(jù)庫內(nèi)部支持標識字段)。如DB2、SQLServer、MySQL中的主鍵生成機制。返回的標識符是long,short或者int類型的。sequence(序列):采用數(shù)據(jù)庫提供的sequence機制生成主鍵。如Oralce中的Sequence。hilo(高低位):通過hi/lo算法實現(xiàn)的主鍵生成機制,需要額外的數(shù)據(jù)庫表保存主鍵生成歷史狀態(tài)。高/低位算法生成的標識符只在一個特定的數(shù)據(jù)庫中是唯一的。在使用JTA獲得的連接或者用戶自行提供的連接中,不要使用這種生成器。seqhilo(使用序列的
38、高低位):與hilo類似,通過hi/lo算法實現(xiàn)的主鍵生成機制,只是主鍵歷史狀態(tài)保存在Sequence中,適用于支持Sequence的數(shù)據(jù)庫,如Oracle。uuid.hex用一個128-bit的UUID算法生成字符串類型的標識符。在一個網(wǎng)絡中唯一(使用了IP地址,JVM的啟動時間(精確到1/4秒),系統(tǒng)時間和一個計數(shù)器值(在JVM中唯一)。)。UUID被編碼為一個32位16進制數(shù)字的字符串。uuid.string使用同樣的UUID算法。UUID被編碼為一個16個字符長的任意ASCII字符組成的字符串native(本地)根據(jù)底層數(shù)據(jù)庫的能力選擇identity,sequence或者hilo中的
39、一個assigned(程序設置)讓應用程序在save()之前為對象分配一個標示符。foreign(外部引用)使用另外一個相關聯(lián)的對象的標識符。和聯(lián)合一起使用。3.4、property元素為類聲明了一個持久化的,JavaBean風格的屬性。(1)name:屬性的名字,以小寫字母開頭。(2)column(可選-默認為屬性名字):對應的數(shù)據(jù)庫字段名。(3)type(可選):一個Hibernate類型的名字。(4)update,insert(可選-默認為true):表明在用于UPDATE和/或INSERT的SQL語句中是否包含這個字段。這二者如果都設置為false則表明這是一個“外源性(derived
40、)”的屬性,它的值來源于映射到同一個(或多個)字段的某些其他屬性,或者通過一個trigger(觸發(fā)器),或者其他程序。(5)formula(可選):一個SQL表達式,定義了這個計算(computed)屬性的值。計算屬性沒有和它對應的數(shù)據(jù)庫字段。(6)access(可選-默認值為property):Hibernate用來訪問屬性值的策略。3.5、多對一個(many-to-one)(1)name:屬性名。(2)column(可選):字段名。(3)class(可選-默認是通過反射得到屬性類型):關聯(lián)的類的名字。(4)cascade(級聯(lián))(可選):指明哪些操作會從父對象級聯(lián)到關聯(lián)的對象。(5)out
41、er-join(外連接)(可選-默認為自動):當設置hibernate.use_outer_join的時候,對這個關聯(lián)允許外連接抓取。(6)update,insert(可選-defaultstotrue)指定對應的字段是否在用于UPDATE和/或INSERT的SQL語句中包含。如果二者都是false,則這是一個純粹的“外源性(derived)”關聯(lián),它的值是通過映射到同一個(或多個)字段的某些其他屬性得到的,或者通過trigger(觸發(fā)器),或者是其他程序。(7)property-ref:(可選)指定關聯(lián)類的一個屬性,這個屬性將會和本外鍵相對應。如果沒有指定,會使用對方關聯(lián)類的主鍵。該屬性只應
42、該用來對付老舊的數(shù)據(jù)庫系統(tǒng),可能出現(xiàn)外鍵指向對方關聯(lián)表的是個非主鍵字段(但是應該是一個惟一關鍵字)的情況。(8)access(可選-默認是property):Hibernate用來訪問屬性的策略。Cascaed級聯(lián)操作總結:會在多的一端加入一個外鍵,指向一的一端,這個外鍵是由中的column屬性定義的,如果忽略了這個屬性那么默認的外鍵與實體的屬性一致Notnull屬性如果設為true,會報異常。建議:通常在或關系中應用級聯(lián)(cascade)沒什么意義。級聯(lián)(cascade)通常在和關系中比較有用。3.6、一對多(one-to-many)(1)name集合屬性的名稱(2)table(可選)目標關
43、聯(lián)數(shù)據(jù)庫表(3)lazy(可選默認為false)允許延遲加載(lazyinitialization)(4)inverse(可選默認為false)標記這個集合作為雙向關聯(lián)關系中的方向一端。(5)cascade(可選默認為none)讓操作級聯(lián)到子實體(6)sort(可選默認為unsorted)指定集合的排序順序,其可以為自然的(natural)或者給定一個用來比較的類。(7)order-by(可選,僅用于jdk1.4)指定表的字段(一個或幾個)再加上asc或者desc(可選),定義Map,Set和Bag的迭代順序(8)where(可選)指定任意的SQLwhere條件。該條件將在重新載入或者刪除這個
44、集合時使用(當集合中的數(shù)據(jù)僅僅是所有可用數(shù)據(jù)的一個子集時這個條件非常有用)(9)outer-join(可選-默認為auto)是否使用外聯(lián)接八、多對多(1)column(必需):中間映射表中,關聯(lián)目標表的關聯(lián)字段(2)class(必需):類名,關聯(lián)目標類(3)outer-join(可選-默認為auto):在Hibernate系統(tǒng)參數(shù)中hibernate.use_outer_join被打開的情況下,該參數(shù)用來允許使用outerjoin來載入此集合的數(shù)據(jù)。3.7、inverse和和cascade區(qū)別3.7.1、inverse屬性inverse所描述的是對象之間關聯(lián)關系的維護方式。inverse只存在
45、于集合標記的元素中。Hibernate提供的集合元素包括Inverse屬性的作用是:是否將對集合對象的修改反映到數(shù)據(jù)庫中。inverse屬性的默認值為false,表示對集合對象的修改會被反映到數(shù)據(jù)庫中inverse=”true”表示對集合對象的修改不會被反映到數(shù)據(jù)庫中。中inverse的屬性的設置例:Person中包含一個Child集合,Child包含一個Person對象。要求:新建Person和Child對象,Child屬于此Person對象分析:在數(shù)據(jù)庫中,就是新增一條Child記錄/one-to-many的inverse的配置publicvoidtestInverse()Qxqx=new
46、Qx();qx.setQx(天山區(qū));Jdjd=newJd();jd.setJd(人民路);qx.getJds().add(jd);jd.setQx(qx);super.add(qx);super.add(jd);配置Inverse=”false”,Hibernate的操作:(1)Hibernate:insertintoTBL_QX(qx)values(?)(2)Hibernate:insertintoTBL_JD(jd,qxid)values(?,?)(3)Hibernate:updateTBL_JDsetqxid=?wherejdid=?配置Inverse=”true”,Hibernate
47、的操作(1)Hibernate:insertintoTBL_QX(qx)values(?)(2)Hibernate:insertintoTBL_JD(jd,qxid)values(?,?)可以看出:Inverse=”true”,SQL少執(zhí)行一條更新操作(Java代碼不會少)中inverse的屬性的設置在多對多的關系中,可以在關聯(lián)的兩邊都不設置inverse屬性(默認的false),那么說明關聯(lián)的雙方都可以維護兩個對象之間的關聯(lián)關系。注:在設置多對多關系的inverse屬性時,不能兩個對象都將其設置為true3.7.2、cascade屬性cascade屬性的作用是描述關聯(lián)對象進行操作時的級聯(lián)特性
48、。因此,只有涉及到關系的元素才有cascade屬性。具有cascade屬性的標記包括注意:和是用在集合標記內(nèi)部的,所以是不需要cascade屬性的。級聯(lián)操作:指當主控方執(zhí)行某項操作時,是否要對被關聯(lián)方也執(zhí)行相同的操作。3.7.3、inverse和cascade的區(qū)別、作用的范圍不同Inverse是設置在集合元素中的。Cascade對于所有涉及到關聯(lián)的元素都有效。沒有inverse屬性,但有cascade屬性、執(zhí)行的策略不同Inverse會首先判斷集合的變化情況,然后針對變化執(zhí)行相應的處理。Cascade是直接對集合中每個元素執(zhí)行相應的處理、執(zhí)行的時機不同Inverse是在執(zhí)行SQL語句之前判斷
49、是否要執(zhí)行該SQL語句Cascade則在主控方發(fā)生操作時用來判斷是否要進行級聯(lián)操作、執(zhí)行的目標不同Inverse對于和處理方式不相同。對于,inverse所處理的是對被關聯(lián)表進行修改操作。對于,inverse所處理的則是中間關聯(lián)表Cascade不會區(qū)分這兩種關系的差別,所做的操作都是針對被關聯(lián)的對象。、總結中,建議inverse=”true”,由“many”方來進行關聯(lián)關系的維護中,只設置其中一方inverse=”false”,或雙方都不設置Cascade,通常情況下都不會使用。特別是刪除,一定要慎重。四、持久化對象的狀態(tài)4.1、對象的狀態(tài)瞬時(Transient)對象:使用new操作符初始化
50、的對象不是立刻就持久的。它們的狀態(tài)是瞬時的,也就是說它們沒有任何跟數(shù)據(jù)庫表相關聯(lián)的行為,只要應用不再引用這些對象(不再被任何其它對象所引用),它們的狀態(tài)將會丟失,并由垃圾回收機制回收。持久化(Persist)對象:持久實例是任何具有數(shù)據(jù)庫標識的實例。它有持久化管理器Session統(tǒng)一管理,持久實例是在事務中進行操作的它們的狀態(tài)在事務結束時同數(shù)據(jù)庫進行同步。當事務提交時,通過執(zhí)行SQL的INSERT、UPDATE和DELETE語句把內(nèi)存中的狀態(tài)同步到數(shù)據(jù)庫中。離線(Detached)對象:Session關閉之后,持久化對象就變?yōu)殡x線對象。離線表示這個對象不能再與數(shù)據(jù)庫保持同步,它們不再受Hibe
51、rnate管理。Save()saveorupdate()update()Automaticdirtyobjectchecking4.2、java對象的生命周期五、Hibernate查詢數(shù)據(jù)查詢與檢索是Hibernate中的一個亮點。相對其他ORM實現(xiàn)而言,Hibernate提供了靈活多樣的查詢機制。HibernateQueryLanguage(HQL)HQL是完全面向對象的查詢語句,具備繼承、多態(tài)和關聯(lián)等特性。HQL(HibernateQueryLanguage)提供了非常強大的查詢功能,在官方開發(fā)手冊中,也將HQL作為推薦的查詢模式。HQL子句本身大小寫無關,但是其中出現(xiàn)的類名和屬性名必須注
52、意大小寫區(qū)分CriteriaQueriesCriteriaQuery(標準化對象查詢)通過面向對象化的設計,將數(shù)據(jù)查詢條件封裝為一個對象。簡單來講,CriteriaQuery可以看作是傳統(tǒng)SQL的對象化表示。優(yōu)點:可讀性好,符合Java程序員的編碼習慣。缺點:不夠成熟,不支持投影(projection)或統(tǒng)計函數(shù)(aggregation)。這種方式的特點是比較符合Java程序員的編碼習慣,并且具備清晰的可讀性。正因為此,不少ORM實現(xiàn)中都提供了類似的實現(xiàn)機制(如ApacheOJB)。NativeSQLQueries原生SQL查詢:直接使用數(shù)據(jù)庫提供的SQL進行查詢。安裝配置下載最新發(fā)布的Hib
53、ernate代碼包,拷貝需要的.jar文件。Hibernate配置有兩中方法:XML格式的配置文件,文件名默認為“hibernate.cfg.xml“。傳統(tǒng)的properties文件配置方式,文件名為“perties”。第一種方式,提供了易讀的結構,和更強的配置能力,可以直接對映射文件加以配置,使用起來更方便。第二種方式比較簡單。User例子實體類:必需有一個默認的構造函數(shù),equal()HashCode()SerializableSession.flush()方法強制數(shù)據(jù)庫同步,這里即強制Hibernate將user實例立即同步到數(shù)據(jù)庫中。如果在事務中則不需要flush方法,在事務提交的時候
54、,hibernate自動會執(zhí)行flush方法,另外當Session關閉時,也會自動執(zhí)行flush方法。session.close()session.flush():刷新,迫使Session執(zhí)行一些必需的SQL語句,把內(nèi)存中的對象和JDBC連接中的狀態(tài)進行同步更新。session.clear():要把所有的對象從session緩存中完全清除在sessionFactory.openSession()中,hibernate會初始化數(shù)據(jù)庫連接,與此同時,將其AutoCommit設為關閉狀態(tài)(false)。而其后,在Session.beginTransaction方法中,Hibernate會再次確認Co
55、nnection的AutoCommit屬性被設為關閉狀態(tài)(為了防止用戶代碼對session的Connection.AutoCommit屬性進行修改)。Set和List的區(qū)別:Query.list();Query.iterate();對于list方法而言,實際上Hibernate是通過一條SelectSQL獲取所有的記錄。并將其讀出,填入到POJO中返回。而iterate方法,則是首先通過一條SelectSQL獲取所有符合查詢條件的記錄的id,再對這個id集合進行循環(huán)操作,通過單獨的SelectSQL取出每個id所對應的記錄,之后填入POJO中返回。也就是說,對于list操作,需要一條SQL完成
56、。而對于iterate操作,需要n+1條SQL。看上去iterate方法似乎有些多余,但在不同的情況下確依然有其獨特的功效,如對海量數(shù)據(jù)的查詢,如果用list方法將結果集一次取出,內(nèi)存的開銷可能無法承受。另一方面,對于我們現(xiàn)在的Cache機制而言,list方法將不會從Cache中讀取數(shù)據(jù),它總是一次性從數(shù)據(jù)庫中直接讀出所有符合條件的記錄。而iterate方法因為每次根據(jù)id獲取數(shù)據(jù),這樣的實現(xiàn)機制也就為從Cache讀取數(shù)據(jù)提供了可能,hibernate首先會根據(jù)這個id在本地Cache內(nèi)尋找對應的數(shù)據(jù),如果沒找到,再去數(shù)據(jù)庫中檢索。如果系統(tǒng)設計中對Cache比較倚重,則請注意編碼中這兩種不同方
57、法的應用組合,有針對性的改善代碼,最大程度提升系統(tǒng)的整體性能表現(xiàn)。Hibernate3發(fā)布beta版本支持EJB3風格對象持久化(2004.12.21)來自:CSDN熊節(jié)昨天(12月20日)Hibernate框架發(fā)布了3.0版本的第一個beta版本。據(jù)作者GavinKing表示,Hibernate3.0將于明年(2005年)第一季度正式發(fā)布。Hibernate是一個基于POJO(Plain-OldJavaObject,普通Java對象)的O/Rmapping框架,也是目前J2EE社群最流行的對象持久化工具。正在制訂中的EJB3規(guī)范就大量借鑒了Hibernate的經(jīng)驗。在beta1版本中,Hib
58、ernate3并未提供對J2SE5.0的支持,這主要是因為出于兼容性的考慮。GavinKing表示,將在2005年逐步引入J2SE5.0提供的新語言特性,例如泛型、元數(shù)據(jù)標注等。Hibernate3主要的新特性包括:實現(xiàn)了EJB3風格的持久化操作。在原有的saveOrUpdate()和saveOrUpdateCopy()兩個方法之外,又提供了EJB3風格的create()和merge()兩個操作。提供更強的映射靈活性。允許將一個類映射到多張表,允許混合使用“每個繼承體系一張表”和“每個子類一張表”的映射策略,等等。支持存儲過程和手寫SQL,并且可以用手寫SQL替代Hibernate自動生成的S
59、QL語句。基于AST(抽象語法樹)的HQL解析。字段級的懶加載。每個屬性都可以在映射描述符中聲明“l(fā)azy=true”,這樣聲明的屬性會到真正使用時才從數(shù)據(jù)庫加載。不過,實現(xiàn)這項功能需要首先在編譯期對字節(jié)碼進行增強。六、Hibernate最佳實踐(BestPractices)使用Configuration裝載映射文件時,不要使用絕對路徑裝載。最好的方式是通過getResourceAsStream()裝載映射文件,這樣Hibernate會從classpath中尋找已配置的映射文件。SessionFactory的創(chuàng)建非常消耗資源,整個應用一般只要一個SessionFactory就夠了,只有多個數(shù)據(jù)庫的時候才會使用多個SessionFactory。在整個應用中,Session和事務應該能夠統(tǒng)一管理。(Spring為Hibernate提供了非常好的支持)將所有的集合屬性配置設置為懶加載(lazy=”true”)。在hibernate2.x版本中,lazy默認值是“false”,但hibernate
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度文化旅游工程居間服務合同范本標準
- 2025年度數(shù)據(jù)中心基礎設施建設監(jiān)理合同
- 曲靖2025年云南曲靖市師宗縣事業(yè)單位委托遴選26人(含遴選)筆試歷年參考題庫附帶答案詳解
- 2025年金屬包裝罐項目可行性研究報告
- 2025至2031年中國豪華三聯(lián)控制臺行業(yè)投資前景及策略咨詢研究報告
- 2025年磨內(nèi)弧砂輪項目可行性研究報告
- 2025年玩具鹿項目可行性研究報告
- 2025年氰戊菊酯項目可行性研究報告
- 惠州2025年廣東惠州市中醫(yī)醫(yī)院第二批招聘聘用人員22人筆試歷年參考題庫附帶答案詳解
- 2025年微波爐溫度傳感器項目可行性研究報告
- 2025年業(yè)務員工作總結及工作計劃模版(3篇)
- 必修3《政治與法治》 選擇題專練50題 含解析-備戰(zhàn)2025年高考政治考試易錯題(新高考專用)
- 二零二五版電商企業(yè)兼職財務顧問雇用協(xié)議3篇
- 課題申報參考:流視角下社區(qū)生活圈的適老化評價與空間優(yōu)化研究-以沈陽市為例
- 深圳2024-2025學年度四年級第一學期期末數(shù)學試題
- 2024-2025學年成都市高新區(qū)七年級上英語期末考試題(含答案)
- 17J008擋土墻(重力式、衡重式、懸臂式)圖示圖集
- 《中南大學模板》課件
- 廣東省深圳市南山區(qū)2024-2025學年第一學期期末考試九年級英語試卷(含答案)
- T-CISA 402-2024 涂鍍產(chǎn)品 切口腐蝕試驗方法
- 后勤安全生產(chǎn)
評論
0/150
提交評論