ITjob就業(yè)培訓(xùn)java教材34_第1頁
ITjob就業(yè)培訓(xùn)java教材34_第2頁
ITjob就業(yè)培訓(xùn)java教材34_第3頁
ITjob就業(yè)培訓(xùn)java教材34_第4頁
ITjob就業(yè)培訓(xùn)java教材34_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

ITjob就業(yè)培訓(xùn)java教材34ITjob就業(yè)培訓(xùn)java教材34ITjob就業(yè)培訓(xùn)java教材34xxx公司ITjob就業(yè)培訓(xùn)java教材34文件編號:文件日期:修訂次數(shù):第1.0次更改批準(zhǔn)審核制定方案設(shè)計,管理制度第三十四章:Hibernate基礎(chǔ)學(xué)習(xí)目標(biāo)理解ORM機制理解Hibernate的工作原理Hibernate的配置和對象-映射文件理解對象持久化Hibernate簡介Hibernate是Java應(yīng)用和關(guān)系數(shù)據(jù)庫之間的橋梁,它負責(zé)Java對象關(guān)系數(shù)據(jù)之間的映射。Hibernate內(nèi)部封裝了通過JDBC訪問數(shù)據(jù)庫的操作,向上層應(yīng)用提供了面向?qū)ο蟮臄?shù)據(jù)訪問API。在Java應(yīng)用中使用Hibernate包含以下步驟。(1)創(chuàng)建Hibernate的配置文件。(2)創(chuàng)建持久化類。(3)創(chuàng)建對象-關(guān)系映射文件。(4)通過HibernateAPI編寫訪問數(shù)據(jù)庫的代碼。建立簡單的Hibernate應(yīng)用本章通過一個簡單的例子customerApp應(yīng)用,演示如何運用Hibernate來訪問關(guān)系數(shù)據(jù)庫。customerApp應(yīng)用的功能非常簡單:通過Hibernate保存、更新、刪除、加載以及查詢Customer對象。創(chuàng)建Hibernate的配置文件Hibernate從其配置文件中讀取和數(shù)據(jù)庫連接有關(guān)的信息,這個配置文件應(yīng)該位于應(yīng)用的classpath中。Hibernate的配置文件有兩種形式:一種是XML格式的文件;還有一種是Java屬性文件,采用“健=值”的形式。下面介紹如何以Java屬性文件的格式來創(chuàng)建Hibernate的配置文件。這種配置文件的默認文件名為。的內(nèi)容如下:==true以上文件包含了一系列屬性及其屬性值,Hibernate將根據(jù)這些屬性來連接數(shù)據(jù)庫,本例為連接MySQL數(shù)據(jù)庫的配置代碼。下表對以上文件中的所有屬性做了描述。屬性描述SQL指定數(shù)據(jù)庫使用的方言指定數(shù)據(jù)庫的驅(qū)動程序指定連接數(shù)據(jù)庫的指定連接數(shù)據(jù)庫的用戶名指定連接數(shù)據(jù)庫的口令如果為true,表示在程序運行時,會在控制臺輸出SQL語句,這有利于跟蹤Hibernate的運行狀態(tài)。默認為false。在應(yīng)用開發(fā)和測試階段,可以把這個屬性設(shè)為true,以便跟蹤和調(diào)試應(yīng)用程序,在應(yīng)用發(fā)布階段,應(yīng)該把這個屬性設(shè)為false,以便減少應(yīng)用的輸出信息,提高運行性能。Hibernate能夠訪問多種關(guān)系數(shù)據(jù)庫,如MySQL、Oracle和Sybase等。盡管多數(shù)關(guān)系數(shù)據(jù)庫都支持標(biāo)準(zhǔn)的SQL語言,但是它們往往還有各自的SQL方言,就象不同地區(qū)的人既能說標(biāo)準(zhǔn)的普通話,還能講各自的方言一樣。屬性用于指定被訪問數(shù)據(jù)庫使用的SQL方言,當(dāng)Hibernate生成SQL查詢語句,或者使用native對象標(biāo)識符生成策略時,都會參考本地數(shù)據(jù)庫的SQL方言。創(chuàng)建持久化類持久化類是指其實例需要被Hibernate持久化到數(shù)據(jù)庫中的類。持久化類通常都是域模型中的實體域類。持久化類符合JavaBean的規(guī)范,包含一些屬性,以及與之對應(yīng)的getXXX()和setXXX()方法。以下定義了一個名為Customer的持久化類。packageimportimportimportpublicclassCustomerimplementsSerializable{privateLongid;privateStringname;privateStringemail;privateStringpassword;privateintphone;privatebooleanmarried;privateStringaddress;privatecharsex;privateStringdescription;privatebyte[]image;privateDatebirthday;privateTimestampregisteredTime;publicCustomer(){}publicLonggetId(){returnid;}publicvoidsetId(Longid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}quals())的結(jié)果是true,就表示customerA和customerB對象指的是同一個客戶,它們和CUSTOMERS表中的同一條記錄對應(yīng)。Hibernate要求持久化類必須提供一個不帶參數(shù)的默認構(gòu)造方法,在程序運行時,Hibernate運用Java反射機制,調(diào)用方法來構(gòu)造持久化類的實例。如果對這個持久化類使用延遲檢索策略,為了使Hibernate能夠在運行時為這個持久化類創(chuàng)建動態(tài)代理,要求持久化類的默認構(gòu)造方法的訪問級別必須是public或protected類型,而不能是default或private類型。在Customer類中沒有引入任何HibernateAPI,Customer類不需要繼承Hibernate的類,或?qū)崿F(xiàn)Hibernate的接口,這提高了持久化類的獨立性。如果日后要改用其他的ORM產(chǎn)品,比如由Hibernate改為OJB,不需要修改持久化類的代碼。創(chuàng)建數(shù)據(jù)庫Schema在本例中,與Customer類對應(yīng)的數(shù)據(jù)庫表名為CUSTOMERS,它在MySQL數(shù)據(jù)庫中的DDL定義如下:createtableCUSTOMERS(IDbigintnotnullprimarykey,NAMEvarchar(15)notnull,EMAILvarchar(128)notnull,PASSWORDvarchar(8)notnull,PHONEint,ADDRESSvarchar(255),SEXchar(1),IS_MARRIEDbit,DESCRIPTIONtext,IMAGEblob,BIRTHDAYdate,REGISTERED_TIMEtimestamp);CUSTOMERS表有一個ID字段,它是表的主鍵,它和Customer類的id屬性對應(yīng)。CUSTOMERS表中的字段使用了各種各樣的SQL類型,參見下表。字段名SQL類型說明IDBIGINT整數(shù),占8字節(jié),取值范圍為:-2^63~2^63-1NAMEVARCHAR變長字符串,占0~255個字節(jié)SEXCHAR定長字符串,占0~255個字節(jié)IS_MARRIEDBIT布爾類型DESCRIPTIONTEXT長文本數(shù)據(jù),占0~65535255字節(jié)。如果字符串長度小于255,可以用VARCHAR或CHAR類型來表示。如果字符串長度大于255,可以定義為TEXT類型。IMAGEBLOB二進制長數(shù)據(jù),占0~65535字節(jié),BLOB是BinaryLargeObject的縮寫。IMAGE在本例中,字段用來存放圖片數(shù)據(jù)BIRTHDAYDATE代表日期,格式為“YYYY-MM-DD”REGISTERED_TIMETIMESTAMP代表日期和時間,格式為“YYYYMMDDHHMMSS”創(chuàng)建對象-關(guān)系映射文件Hibernate采用XML格式的文件來指定對象和關(guān)系數(shù)據(jù)之間的映射。在運行時,Hibernate將根據(jù)這個映射文件來生成各種SQL語句。在本例中,將創(chuàng)建一個名為的文件,它用于把Customer類映射到CUSTOMERS表,這個文件應(yīng)該和文件存放在同一個目錄下。以下為文件的源代碼。<xmlversion=""><!DOCTYPEhibernate-mappingPUBLIC"-java]Errorreadingresource:mypack/at把Customer持久化類映射到CUSTOMERS表文件用于映射Customer類。如果需要映射多個持久化類,那么既可以在同一個映射文件中映射所有類,也可以為每個類創(chuàng)建單獨的映射文件,映射文件和類同名,擴展名為“”。后一種做法更值得推薦,因為在團隊開發(fā)中,這有利于管理和維護映射文件。<class>元素指定類和表的映射,它的name屬性設(shè)定類名,table屬性設(shè)定表名。以下代碼表明和Customer類對應(yīng)的表為CUSTOMERS表:<classname=""table="CUSTOMERS">如果沒有設(shè)置<class>元素的table屬性,Hibernate將直接以類名作為表名,也就是說,默認情況下,與類對應(yīng)的表為Customer表。<class>元素包含一個<id>子元素以及多個<property>子元素。<id>子元素設(shè)定持久化類的OID和表的主鍵的映射。以下代碼表明Customer類的id屬性和CUSTOMERS表中的ID字段對應(yīng)。<idname="id"column="ID"type="long"><generatorclass="increment"/></id><id>元素的<generator>子元素指定對象標(biāo)識符生成器,它負責(zé)為OID生成惟一標(biāo)識符。<property>子元素設(shè)定類的屬性和表的字段的映射。<property>子元素主要包括name、type、column和not-null屬性。1.<property>元素的name屬性<property>元素的name屬性指定持久化類的屬性的名字。2.<property>元素的type屬性<property>元素的type屬性指定Hibernate映射類型。Hibernate映射類型是Java類型與SQL類型的橋梁。3.<property>元素的not-null屬性如果<property>元素的not-null屬性為true,表明不允許為null,默認為false。例如以下代碼表明不允許Customer類的name屬性為null:<propertyname="name"column="NAME"type="string"not-null="true"/>Hibernate在持久化一個Customer對象時,會先檢查它的name屬性是否為null,如果為null,就會拋出以下異常:not-nullpropertyreferencesanullortransientvalue:如果數(shù)據(jù)庫中CUSTOMERS表的NAME字段不允許為null,但在映射文件中沒有設(shè)置not-null屬性:<propertyname="name"column="NAME"type="string"/>那么Hibernate在持久化一個Customer對象時,不會先檢查它的name屬性是否為null而是直接通過JDBCAPI向CUSTOMERS表插入相應(yīng)的數(shù)據(jù),由于CUSTOMERS表的NAME字段設(shè)置了notnull約束,因此數(shù)據(jù)庫會拋出錯誤:708ERRORJDBCExceptionReporter:58-Generalerror,messagefromserver:"Column'NAME'cannotbenull"4.<property>元素的column屬性<property>元素的column屬性指定與類的屬性映射的表的字段名。以下代碼表明和address屬性對應(yīng)的字段為ADDRESS字段:<propertyname="address"column="ADDRESS"type="string"/>如果沒有設(shè)置<property>元素的column屬性,Hibernate將直接以類的屬性名作為字段名,也就是說,默認情況下,與Customer類的address屬性對應(yīng)的字段為address字段。<property>元素還可以包括<column>子元素,它和<property>元素的column屬性一樣,都可以設(shè)定與類的屬性映射的表的字段名。以下兩種設(shè)置方式是等價的:<propertyname="address"column="ADDRESS"type="string"/>或者<propertyname="address"type="string"><columnname="ADDRESS"/></property><property>元素的<column>子元素比column屬性提供更多的功能,它可以更加詳細的描述表的字段。例如以下<column>子元素指定CUSTOMERS表中的NAME字段的SQL類型為varchar(15),不允許為null,并且為這個字段建立了索引:<propertyname="name"type="string"><columnname="NAME"sql-type="varchar(15)"not-null="true"index="idx_name"/></property>通過HibernateAPI操縱數(shù)據(jù)庫Hibernate對JDBC進行了封裝,提供了更加面向?qū)ο蟮腁PI。以下兩圖對比了直接通過JDBCAPI以及通過HibernateAPI來訪問數(shù)據(jù)庫的兩種方式。以下示例的BusinessService類演示了通過HibernateAPI對Customer對象進行持久化的操作。packageimport.*;importimportimport.*;importimportimport.*;publicclassBusinessService{publicstaticSessionFactorysessionFactory;/**初始化Hibernate,創(chuàng)建SessionFactory實例*/static{try{publicvoidsaveCustomer(Customercustomer)throwsException{……}/**按照OID加載一個Customer對象,然后修改它的屬性*/publicvoidloadAndUpdateCustomer(Longcustomer_id,Stringaddress)throwsException{……}/**刪除所有的Customer對象*/publicvoiddeleteAllCustomers()throwsException{Sessionsession=();Transactiontx=null;try{tx=();("fromCustomerasc");();}catch(Exceptione){if(tx!=null){();}throwe;}finally{();}}/**選擇向控制臺還是動態(tài)網(wǎng)頁輸出Customer對象的信息*/privatevoidprintCustomer(ServletContextcontext,OutputStreamout,Customercustomer)throwsException{if(outinstanceofServletOutputStream)printCustomer(context,(ServletOutputStream)out,customer);elseprintCustomer((PrintStream)out,customer);}/**把Customer對象的信息輸出到控制臺,如DOS控制臺*/privatevoidprintCustomer(PrintStreamout,Customercustomer)throwsException{……}/**把Customer對象的信息輸出到動態(tài)網(wǎng)頁*/privatevoidprintCustomer(ServletContextcontext,ServletOutputStreamout,Customercustomer)throwsException{……}publicvoidtest(ServletContextcontext,OutputStreamout)throwsException{Customercustomer=newCustomer();("Tom");");("("1234");();("Shanghai");('M');("Iamveryhonest.");etResourceAsStream("");byte[]buffer=newbyte[()];(buffer);(buffer);1980-05-06Beijing();}}以上例子演示了通過HibernateAPI訪問數(shù)據(jù)庫的一般流程。首先應(yīng)該在應(yīng)用的啟動階段對Hibernate進行初始化,然后就可以通過Hibernate的Session接口來訪問數(shù)據(jù)庫。Hibernate的初始化BusinessService類的靜態(tài)代碼塊負責(zé)Hibernate的初始化工作,如讀取Hibernate的配置信息以及對象-關(guān)系映射信息,最后創(chuàng)建SessionFactory實例。當(dāng)JVM(Java虛擬機)加載BusinessService類時,會執(zhí)行該靜態(tài)代碼塊。初始化過程包括如下步驟。(1)創(chuàng)建一個Configuration類的實例,Configuration類的構(gòu)造方法把默認文件路徑下的配置文件中的配置信息讀入到內(nèi)存:Configurationconfig=newConfiguration();(2)調(diào)用Configuration類的addClass方法:;該方法把默認文件路徑下的文件中的映射信息讀入到內(nèi)存中。(3)調(diào)用Configuration類的buildSessionFactory()方法:sessionFactory=();該方法創(chuàng)建一個SessionFactory實例,并把Configuration對象包含的所有配置信息拷貝到SessionFactory對象的緩存中。SessionFactory代表一個數(shù)據(jù)庫存儲源,如果應(yīng)用只有一個數(shù)據(jù)庫存儲源,那么只需創(chuàng)建一個SessionFactory實例。當(dāng)SessionFactory對象創(chuàng)建后,該對象不和Configuration對象關(guān)聯(lián)。因此如果再修改Configuration對象包含的配置信息,不會對SessionFactory對象有任何影響。訪問Hibernate的Session接口初始化過程結(jié)束后,就可以調(diào)用SessionFactory實例的openSession()方法來獲得Session實例,然后通過它執(zhí)行訪問數(shù)據(jù)庫的操作。Session接口提供了操縱數(shù)據(jù)庫的各種方法,如:save()方法:把Java對象保存數(shù)據(jù)庫中。update()方法:更新數(shù)據(jù)庫中的Java對象。delete()方法:把Java對象從數(shù)據(jù)庫中刪除。load()方法:從數(shù)據(jù)庫中加載Java對象。find()方法:從數(shù)據(jù)庫中查詢Java對象。Session是一個輕量級對象。通常將每一個Session實例和一個數(shù)據(jù)庫事務(wù)綁定,也就是說,每執(zhí)行一個數(shù)據(jù)庫事務(wù),都應(yīng)該先創(chuàng)建一個新的Session實例。如果事務(wù)執(zhí)行中出現(xiàn)異常,應(yīng)該撤銷事務(wù)。不論事務(wù)執(zhí)行成功與否,最后都應(yīng)該調(diào)用Session的close()方法,從而釋放Session實例占用的資源。以下代碼演示了用Session來執(zhí)行事務(wù)的流程,其中Transaction類用來控制事務(wù)。Sessionsession=();Transactiontx;try{.Shanghai,values(1,'Tom',','1980-05-06',null)在test()方法中并沒有設(shè)置Customer對象的id屬性,Hibernate會根據(jù)映射文件的配置,采用increment標(biāo)識符生成器自動以遞增的方式為OID賦值。在文件中相關(guān)的映射代碼如下:<idname="id"column="ID"type="long"><generatorclass="increment"/></id>在test()方法中也沒有設(shè)置Customer對象的registeredTime屬性,因此在以上insert語句中,REGISTERED_TIME字段的值為null。但由于REGISTERED_TIME字段的SQL類型為TIMESTAMP類型,如果insert語句沒有為TIMESTAMP類型的字段賦值,底層數(shù)據(jù)庫會自動把當(dāng)前的系統(tǒng)時間賦值給TIMESTAMP類型的字段。因此,執(zhí)行完以上insert語句后,REGISTERED_TIME字段的值并不為null,而是插入該記錄時的系統(tǒng)時間。2.findAllCustomers()方法該方法調(diào)用Session的find()方法,查詢所有的Customer對象。tx=();Listcustomers=("fromCustomerascorderbyasc");for(Iteratorit=();();){printCustomer(context,out,(Customer)());}();Session的find()方法有好幾種重載形式,本例中傳遞的是字符串參數(shù)“fromCustomerascorderbyasc”,它使用的是Hibernate查詢語言。運行()方法時,Hibernate執(zhí)行以下SQL語句:select*fromCUSTOMERSorderbyNAMEasc;3.loadAndUpdateCustomer()方法該方法調(diào)用Session的load()方法,加載Customer對象,然后再修改Customer對象的屬性。tx=();Customerc=(Customer),customer_id);(address);();以上代碼先調(diào)用Session的load()方法,它按照參數(shù)指定的OID從數(shù)據(jù)庫中檢索出匹配的Customer對象,Hibernate會執(zhí)行以下SQL語句:select*fromCUSTOMERSwhereID=1;loadAndUpdateCustomer()方法接著修改Customer對象的address屬性。那么,Hibernate會不會同步更新數(shù)據(jù)庫中相應(yīng)的CUSTOMERS表的記錄呢答案是肯定的。Hibernate采用臟檢查機制,按照內(nèi)存中的Customer對象的狀態(tài)的變化,來同步更新數(shù)據(jù)庫中相關(guān)的數(shù)據(jù),Hibernate會執(zhí)行以下SQL語句:updateCUSTOMERSsetNAME="Tom",EMAIL=""…ADDRESS="Beijing"…盡管只有Customer對象的address屬性發(fā)生了變化,但是Hibernate執(zhí)行的update語句中會包含所有的字段。在BusinessService類的test()方法中按如下方式調(diào)用loadAndUpdateCustomer()方法:saveCustomer(customer);loadAndUpdateCustomer(),"Beijing");以上代碼并沒有直接給customer對象的id屬性賦值,當(dāng)執(zhí)行saveCustomer(customer)方法時,Session的save()方法把customer對象持久化到數(shù)據(jù)庫中,并自動為id屬性賦值。4.printCustome

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論