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

下載本文檔

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

文檔簡(jiǎn)介

第三十四章:Hibernate基礎(chǔ)學(xué)習(xí)目標(biāo)理解ORM機(jī)希9理解Hibernate的工作原理Hibernate的配置和對(duì)象-映射文件理解對(duì)象持久化Hibernate簡(jiǎn)介Hibernate是Java應(yīng)用和關(guān)系數(shù)據(jù)庫(kù)之間的橋梁,它負(fù)責(zé)Java對(duì)象關(guān)系數(shù)據(jù)之間的映射。Hibernate內(nèi)部封裝了通過(guò)JDBC訪問(wèn)數(shù)據(jù)庫(kù)的操作,向上層應(yīng)用提供了面向?qū)ο蟮臄?shù)據(jù)訪問(wèn)API。在Java應(yīng)用中使用Hibernate包含以下步驟。(1) 創(chuàng)建Hibernate的配置文件。(2) 創(chuàng)建持久化類。(3) 創(chuàng)建對(duì)象-關(guān)系映射文件。(4) 通過(guò)HibernateAPI編寫訪問(wèn)數(shù)據(jù)庫(kù)的代碼。建立簡(jiǎn)單的Hibernate應(yīng)用本章通過(guò)一個(gè)簡(jiǎn)單的例子customerApp應(yīng)用,演示如何運(yùn)用Hibernate來(lái)訪問(wèn)關(guān)系數(shù)據(jù)庫(kù)。customerApp應(yīng)用的功能非常簡(jiǎn)單:通過(guò)Hibernate保存、更新、刪除、加載以及查詢Customer對(duì)象。創(chuàng)建Hibernate的配置文件Hibernate從其配置文件中讀取和數(shù)據(jù)庫(kù)連接有關(guān)的信息,這個(gè)配置文件應(yīng)該位于應(yīng)用的classpath中。Hibernate的配置文件有兩種形式:一種是XMI格式的文件;還有一種是Java屬性文件,采用“健=值”的形式。下面介紹如何以Java屬性文件的格式來(lái)創(chuàng)建Hibernate的配置文件。這種配置文件的默認(rèn)文件名為hiberperties。perties的內(nèi)容如下:hibernate.show_sql=true以上perties文件包含了一系列屬性及其屬性值,Hibernate將根據(jù)這些屬性來(lái)連接數(shù)據(jù)庫(kù),本例為連接MySQL數(shù)據(jù)庫(kù)的配置代碼。下表對(duì)以上perties 文件中的所有屬性做了描述。屬性描述hibernate.dialectSQL指定數(shù)據(jù)庫(kù)使用的方言指定數(shù)據(jù)庫(kù)的驅(qū)動(dòng)程序URL指定連接數(shù)據(jù)庫(kù)的指定連接數(shù)據(jù)庫(kù)的用戶名指定連接數(shù)據(jù)庫(kù)的口令hibernate.show_sql如果為true,表示在程序運(yùn)行時(shí),會(huì)在控制臺(tái)輸岀 SQL語(yǔ)句,這有利于跟蹤 Hibernate 的運(yùn)行狀態(tài)。默認(rèn)為false。在應(yīng)用開(kāi)發(fā)和測(cè)試階段,可以把這個(gè)屬性設(shè)為true,以便跟蹤和調(diào)試應(yīng)用程序,在應(yīng)用發(fā)布階段,應(yīng)該把這個(gè)屬性設(shè)為 false,以便減少應(yīng)用的輸岀信息,提高運(yùn)行性能。Hibernate能夠訪問(wèn)多種關(guān)系數(shù)據(jù)庫(kù),如MySQLOracle和Sybase等。盡管多數(shù)關(guān)系數(shù)據(jù)庫(kù)都支持標(biāo)準(zhǔn)的SQL語(yǔ)言,但是它們往往還有各自的SQL方言,就象不同地區(qū)的人既能說(shuō)標(biāo)準(zhǔn)的普通話,還能講各自的方言一樣。hibernate.dialect屬性用于指定被訪問(wèn)數(shù)據(jù)庫(kù)使用的SQL方言,當(dāng)Hibernate生成SQL查詢語(yǔ)句,或者使用native對(duì)象標(biāo)識(shí)符生成策略時(shí),都會(huì)參考本地?cái)?shù)據(jù)庫(kù)的 SQL方言。創(chuàng)建持久化類持久化類是指其實(shí)例需要被Hibernate持久化到數(shù)據(jù)庫(kù)中的類。持久化類通常都是域模型中的實(shí)體域類。持久化類符合JavaBean的規(guī)范,包含一些屬性,以及與之對(duì)應(yīng)的getXXX()和setXXX()方法。以下定義了一個(gè)名為Customer的持久化類。package;importimportimportpublicclassCustomerimplementsSerializable{privateLongid;privateStringname;privateStringemail;privateStringpassword;privateintphone;privatebooleanmarried;privateStringaddress;privatecharsex;privateStringdescription;privatebyte[]image;privateDatebirthday;privateTimestampregisteredTime;publicCustomer(){}publicLonggetId(){returnid;}publicvoidsetId(Longid){this.id=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}//此處省略email、password和phone等屬性的getXXX()和setXXX()方法}持久化類符合JavaBean的規(guī)范,包含一些屬性,以及與之對(duì)應(yīng)的getXXX()和setXXX()方法。getXXX()和setXXX()方法必須符合特定的命名規(guī)則,“get”和“set”后面緊跟屬性的名字,并且屬性名的首字母為大寫,例如name屬性的get方法為getName(),如果把get方法寫為getname()或者getNAME(),會(huì)導(dǎo)致Hibernate在運(yùn)行時(shí)拋出以下異常:Couldnotfindagetterforpropertynameinclass.Customer如果持久化類的屬性為boolean類型,那么它的get方法名既可以用“get”作為前綴,也可以用“is”作為前綴。例如Customer類的married屬性為boolean類型,因此以下兩種get方法是等價(jià)的:publicbooleanisMarried(){returnmarried;}或者publicbooleangetMarried(){returnmarried;}Hibernate并不要求持久化類必須實(shí)現(xiàn)接口,但是對(duì)于采用分布式結(jié)構(gòu)的Java應(yīng)用,當(dāng)Java對(duì)象在不同的進(jìn)程節(jié)點(diǎn)之間傳輸時(shí),這個(gè)對(duì)象所屬的類必須實(shí)現(xiàn)Serializable接口,此外,在JavaWeb應(yīng)用中,如果希望對(duì)HttpSession中存放的Java對(duì)象進(jìn)行持久化,那么這個(gè)Java對(duì)象所屬的類也必須實(shí)現(xiàn)Serializable接口。Customer持久化類有一個(gè)id屬性,用來(lái)惟一標(biāo)識(shí)Customer類的每個(gè)對(duì)象。在面向?qū)ο笮g(shù)語(yǔ)中,這個(gè)id屬性被稱為對(duì)象標(biāo)識(shí)符(OID,ObjectIdentifier),通常它都用整數(shù)表示,當(dāng)然也可以設(shè)為其他類型。如果customerA.getId().equals(customerB.getId())的結(jié)果是true,就表示customerA和customerB對(duì)象指的是同一個(gè)客戶,它們和 CUSTOMER表中的同一條記錄對(duì)應(yīng)。Hibernate要求持久化類必須提供一個(gè)不帶參數(shù)的默認(rèn)構(gòu)造方法,在程序運(yùn)行時(shí),Hibernate運(yùn)用JavaHibernate能夠在運(yùn)行時(shí)為這個(gè)持久化類創(chuàng)建動(dòng)態(tài)代理,要求持久化類的默認(rèn)構(gòu)造方法的訪問(wèn)級(jí)別必須是public或protected類型,而不能是default或private類型。在Customer類中沒(méi)有引入任何HibernateAPI,Customer類不需要繼承Hibernate的類,或?qū)崿F(xiàn)Hibernate的接口,這提高了持久化類的獨(dú)立性。如果日后要改用其他的ORM產(chǎn)品,比如由Hibernate改為OJB不需要修改持久化類的代碼。創(chuàng)建數(shù)據(jù)庫(kù)Schema在本例中,與Customer類對(duì)應(yīng)的數(shù)據(jù)庫(kù)表名為CUSTOMER它在MySQ數(shù)據(jù)庫(kù)中的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有一個(gè)ID字段,它是表的主鍵,它和Customer類的id屬性對(duì)應(yīng)。CUSTOMERS^的字段使用了各種各樣的SQL類型,參見(jiàn)下表。字段名SQL類型說(shuō)明IDBIGINT:整數(shù),占8字節(jié),取值范圍為:-2A63~2A63-1NAMEVARCHAR變長(zhǎng)字符串,占0~255個(gè)字節(jié)SEXCHAR定長(zhǎng)字符串,占0~255個(gè)字節(jié)ISMARRIEDBIT:布爾類型DESCRIPTIONTEXT長(zhǎng)文本數(shù)據(jù),占0~65535255字節(jié)。如果字符串長(zhǎng)度小于255,可以用VARCHA或CHAF類型來(lái)表示。如果字符串長(zhǎng)度大于255,可以定義為TEXT類型。IMAGEBLOB二進(jìn)制長(zhǎng)數(shù)據(jù),占0~65535字節(jié),BLOB是BinaryLargeObject的縮與。IMAGE在本例中,字段用來(lái)存放圖片數(shù)據(jù)BIRTHDAYDATE:代表日期,格式為“丫丫丫丫-MM-DDREGISTERED」"1RIMESTAMP代表日期和時(shí)間,格式為“YYYYMMDDHHMMSS創(chuàng)建對(duì)象-關(guān)系映射文件Hibernate采用XML格式的文件來(lái)指定對(duì)象和關(guān)系數(shù)據(jù)之間的映射。在運(yùn)行時(shí),Hibernate將根據(jù)這個(gè)映射文件來(lái)生成各種 SQL語(yǔ)句。在本例中,將創(chuàng)建一個(gè)名為Customer類映射到CUSTOMER^這個(gè)文件應(yīng)該和Customer.classv?xmlversion="1.0"?><!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD2.0//EN"">vhibernate-mapping><classname="mypack.Customer"table="CUSTOMERS"><idname="id"column="ID"type="long"><generatorclass="increment"/></id><propertyname="name"column="NAME"type="string"not-null="true"/><propertyname="email"column="EMAIL"type="string"not-null="true"/><propertyname="password"column="PASSWORD"type="string"not-null="true"/><propertyname="phone"column="PHONE"type="int"/><propertyname="address"column="ADDRESS"type="string"/><propertyname="sex"column="SEX"type="character"/><propertyname="married"column="IS_MARRIED"type="boolean"/><propertyname="description"column="DESCRIPTION"type="text"/><propertyname="image"column="IMAGE"type="binary"/><propertyname="birthday"column="BIRTHDAY"type="date"/><propertyname="registeredTime"column="REGISTERED_TIME"type="timestamp"/></class>v/hibernate-mapping>映射文件的文檔類型定義(DTDDTD(DocumentTypeDefinition,文檔類型定義),它對(duì)XML文件的語(yǔ)法和格式作了定義。Hibernate的XMLS析器將根據(jù)DTD來(lái)核對(duì)XML文件的語(yǔ)法。每一種XML文件都有獨(dú)自的DTD文件。Hibernate的對(duì)象-關(guān)系映射文件使用的。此外,在Hibernate軟件包的src\net\sf\hibernate 目錄下也提供了<!ELEMENThibernate-mapping(meta*,import*,(class|subclass|joined-subclass)*,query*,sql-query*)>描述頂層元素<hibernate-mapping>的子元素<class>的代碼如下:<!ELEMENTclass(meta*,(cache|jcs-cache)?,(id|composite-id),discriminator?,(version|timestamp)?,(property|many-to-one|one-to-one|component|dynamic-component|any|map|set|list|bag|idbag|array|primitive-array)*,((subclass*)|(joined-subclass*)))><hibernate-mapping>元素是對(duì)象-關(guān)系映射文件的根元素,其他元素(即以上 DTD代碼中括號(hào)以內(nèi)的元素,女口 <class>子元素)必須嵌入在vhibernate-mapping>元素以內(nèi)。在<class>元素中又嵌套了好多子元素。在以上 DTD弋碼中,還使用了一系列的特殊符號(hào)來(lái)修飾元素,下表描述了這些符號(hào)的作用。在創(chuàng)建自己的對(duì)象 -關(guān)系映射文件時(shí),如果不熟悉某種元素的語(yǔ)法,可以參考 DTD文件。DTD中特殊符號(hào)的作用符號(hào)含義無(wú)符號(hào)該子兀素在父兀素內(nèi)必須存在且只能存在一次。+該子元素在父元素內(nèi)必須存在,可以存在一次或者多次。*該子元素在父元素內(nèi)可以不存在,或者存在一次或者多次。它是比較常用的符號(hào)。?該子元素在父元素內(nèi)可以不存在,或者只存在一次。它是比較常用的符號(hào)。表2-3可以看出,在<hibernate-mapping>元素中,<meta>、<import>、<class>和<query>等子元素可以不存在,或者存在一次或者多次;在 <class>元素中,<id>子元素必須存在且只能存在一次,<property>元素可以不存在,或者存在一次或者多次。此外,在映射文件中,父元素中的各種子元素的定義必須符合特定的順序。例如根據(jù)<class>元素的DTD可以看出,必須先定義<id>子元素,再定義<property>子元素,以下映射代碼顛倒了<id>和<property>子元素的位置:<classname="mypack.Customer"table="CUSTOMERS"><propertyname="name"column="NAME"type="string"not-null="true"/><propertyname="email"column="EMAIL"type="string"not-null="true"/><idname="id"column="ID"type="long"><generatorclass="increment"/></id></class>Hibernate的XML解析器在運(yùn)行時(shí)會(huì)拋出MappingException:[java]21:27:51,61OERRORXMLHelper:48-ErrorparsingXML:XMLInputStream(24)Thecontentofelementtype"class"mustmatch"(meta*,(cache|jcs-cache)?,(id|composite-id),discriminator?,(version|timestamp)?,(property|many-to-one|one-to-one|component|dynamic-component|any|map|set|list|bag|idbag|array|primitive-array)*,(subclass*|joined-subclass*))".[java]Errorreadingresource:at把Customer持久化類映射到CUSTOMERSCustomer類。如果需要映射多個(gè)持久化類,那么既可以在同一個(gè)映射文件中映射所有類,也可以為每個(gè)類創(chuàng)建單獨(dú)的映射文件,映射文件和類同名,擴(kuò)展名為“hbm.xml”。后一種做法更值得推薦,因?yàn)樵趫F(tuán)隊(duì)開(kāi)發(fā)中,這有利于管理和維護(hù)映射文件。<class>元素指定類和表的映射,它的 name屬性設(shè)定類名,table屬性設(shè)定表名。以下代碼表明和Customer類對(duì)應(yīng)的表為CUSTOMERS<classname="mypack.Customer"table="CUSTOMERS">如果沒(méi)有設(shè)置<class>元素的table屬性,Hibernate將直接以類名作為表名,也就是說(shuō),默認(rèn)情況下,與mypack.Customer類對(duì)應(yīng)的表為Customer表。<class>元素包含一個(gè)<id>子元素以及多個(gè)<property>子元素。<id>子元素設(shè)定持久化類的OID和表的主鍵的映射。以下代碼表明Customer類的id屬性和CUSTOMERS^的ID字段對(duì)應(yīng)。<idname="id"column="ID"type="long"><generatorclass="increment"/></id><id>元素的vgenerator>子元素指定對(duì)象標(biāo)識(shí)符生成器,它負(fù)責(zé)為OID生成惟一標(biāo)識(shí)符。<property>子元素設(shè)定類的屬性和表的字段的映射。<property>子元素主要包括name、type、column和not-null屬性。<property>元素的name屬性<property>元素的name屬性指定持久化類的屬性的名字。<property>元素的type屬性<property>元素的type屬性指定Hibernate映射類型。Hibernate映射類型是Java類型與SQL類型的橋梁。<property>元素的not-null屬性如果<property>元素的not-null屬性為true,表明不允許為null,默認(rèn)為false。例如以下代碼表明不允許Customer類的name屬性為null:<propertyname="name"column="NAME"type="string"not-null="true"/>Hibernate在持久化一個(gè)Customer對(duì)象時(shí),會(huì)先檢查它的name屬性是否為null,如果為null,就會(huì)拋出以下異常:not-nullpropertyreferencesanullortransientvalue:.C如果數(shù)據(jù)庫(kù)中CUSTOMERS的NAME字段不允許為null,但在映射文件中沒(méi)有設(shè)置not-null屬性:<propertyname="name"column="NAME"type="string"/>那么Hibernate在持久化一個(gè)Customer對(duì)象時(shí),不會(huì)先檢查它的name屬性是否為null而是直接通過(guò)JDBCAPI向CUSTOMERS插入相應(yīng)的數(shù)據(jù),由于CUSTOMERS的NAM字段設(shè)置了notnull約束,因此數(shù)據(jù)庫(kù)會(huì)拋出錯(cuò)誤:708ERRORJDBCExceptionReporter:58-Generalerror,messagefromserver:"Column'NAME'cannotbenull"<property>元素的column屬性<property>元素的column屬性指定與類的屬性映射的表的字段名。以下代碼表明和address屬性對(duì)應(yīng)的字段為ADDRES字段:<propertyname="address"column="ADDRESS"type="string"/>如果沒(méi)有設(shè)置<property>元素的column屬性,Hibernate將直接以類的屬性名作為字段名,也就是說(shuō),默認(rèn)情況下,與Customer類的address屬性對(duì)應(yīng)的字段為address字段。<property>元素還可以包括<column>子元素,它和<property>元素的column屬性一樣,都可以設(shè)定與類的屬性映射的表的字段名。以下兩種設(shè)置方式是等價(jià)的:<propertyname="address"column="ADDRESS"type="string"/>或者<propertyname="address"type="string"><columnname="ADDRESS"/></property><property>元素的vcolumn*元素比column屬性提供更多的功能,它可以更加詳細(xì)的描述表的字段。例如以下vcolumn>子元素指定CUSTOMERS中的NAME?段的SQL類型為varchar(15),不允許為null,并且為這個(gè)字段建立了索引:vpropertyname="name"type="string">vcolumnname="NAME"sql-type="varchar(15)"not-null="true"index="idx_name"/>v/property>通過(guò)HibernateAPI操縱數(shù)據(jù)庫(kù)Hibernate對(duì)JDBC進(jìn)行了封裝,提供了更加面向?qū)ο蟮?API。以下兩圖對(duì)比了直接通過(guò)JDBCAP以及通過(guò)HibernateAPI來(lái)訪問(wèn)數(shù)據(jù)庫(kù)的兩種方式。以下示例的BusinessService類演示了通過(guò)HibernateAPI對(duì)Customer對(duì)象進(jìn)行持久化的操作。package;importjavax.servlet.*;importimportimportjava.io.*;importimportimportjava.util.*;publicclassBusinessService{publicstaticSessionFactorysessionFactory;/**初始化Hibernate,創(chuàng)建SessionFactory實(shí)例*/static{try{//根據(jù)默認(rèn)位置的Hibernate配置文件的配置信息,創(chuàng)建一個(gè)Configuration實(shí)例Configurationconfig=newConfiguration();config.addClass(Customer.class);//創(chuàng)建SessionFactory實(shí)例*/sessionFactory=config.buildSessionFactory();}catch(Exceptione){e.printStackTrace();}}/**查詢所有的Customer對(duì)象,然后調(diào)用printCustomer()方法打印Customer對(duì)象信息*/publicvoidfindAllCustomers(ServletContextcontext,OutputStreamout)throwsExcTOC\o"1-5"\h\zeption{ }/**持久化一個(gè)Customer對(duì)象*./publicvoidsaveCustomer(Customercustomer)throwsException{ }/**按照OID加載一個(gè)Customer對(duì)象,然后修改它的屬性*/publicvoidloadAndUpdateCustomer(Longcustomer_id,Stringaddress)throwsException{ }/**刪除所有的Customer對(duì)象*/publicvoiddeleteAllCustomers()throwsException{Sessionsession=sessionFactory.openSession();Transactiontx=null;try{tx=session.beginTransaction();session.delete("fromCustomerasc");mit();}catch(Exceptione){if(tx!=null){tx.rollback();}throwe;}finally{session.close();}}/**選擇向控制臺(tái)還是動(dòng)態(tài)網(wǎng)頁(yè)輸出 Customer對(duì)象的信息*/privatevoidprintCustomer(ServletContextcontext,OutputStreamout,Customercustomer)throwsException{if(outinstanceofServletOutputStream)printCustomer(context,(ServletOutputStream)out,customer);elseprintCustomer((PrintStream)out,customer);}/**把Customer對(duì)象的信息輸出到控制臺(tái),如 DOS空制臺(tái)*/privatevoidprintCustomer(PrintStreamout,Customercustomer)throwsException{……}/**把Customer對(duì)象的信息輸出到動(dòng)態(tài)網(wǎng)頁(yè)*/privatevoidprintCustomer(ServletContextcontext,ServletOutputStreamout,Customercustomer)throwsException{……}publicvoidtest(ServletContextcontext,OutputStreamout)throwsException{Customercustomer=newCustomer();customer.setName("Tom");");customer.setPassword("1234");customer.setAddress("Shanghai");customer.setSex('M');customer.setDescription("Iamveryhonest.");//設(shè)置Customer對(duì)象的image屬性,它是字節(jié)數(shù)組,存放photo.gif文件中的二進(jìn)//photo.gif文件和BusinessService.class文件位于同一個(gè)目錄下InputStreamin=this.getClass().getResourceAsStream("photo.gif");byte[]buffer=newbyte[in.available()];in.read(buffer);customer.setImage(buffer);customer.setBirthday(Date.valueOf("1980-05-06"));saveCustomer(customer);findAllCustomers(context,out);loadAndUpdateCustomer(customer.getId(),"Beijing");findAllCustomers(context,out);deleteAllCustomers();}publicstaticvoidmain(Stringargs[])throwsException{newBusinessService().test(null,System.out);sessionFactory.close();}}以上例子演示了通過(guò)HibernateAPI訪問(wèn)數(shù)據(jù)庫(kù)的一般流程。首先應(yīng)該在應(yīng)用的啟動(dòng)階段對(duì)Hibernate進(jìn)行初始化,然后就可以通過(guò)Hibernate的Session接口來(lái)訪問(wèn)數(shù)據(jù)庫(kù)。Hibernate的初始化BusinessService類的靜態(tài)代碼塊負(fù)責(zé)Hibernate的初始化工作,如讀取Hibernate的配置信息以及對(duì)象-關(guān)系映射信息,最后創(chuàng)建SessionFactory實(shí)例。當(dāng)JVM(Java虛擬機(jī))加載BusinessService類時(shí),會(huì)執(zhí)行該靜態(tài)代碼塊。初始化過(guò)程包括如下步驟。創(chuàng)建一個(gè)Configuration類的實(shí)例,Configuration類的構(gòu)造方法把默認(rèn)文件路徑下的perties配置文件中的配置信息讀入到內(nèi)存:Configurationconfig=newConfiguration();調(diào)用Configuration類的addClass(Customer.class)方法:config.addClass(Customer.class);調(diào)用Configuration類的buildSessionFactory()方法:sessionFactory=config.buildSessionFactory();該方法創(chuàng)建一個(gè)SessionFactory實(shí)例,并把Configuration對(duì)象包含的所有配置信息拷貝到SessionFactory對(duì)象的緩存中。SessionFactory代表一個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)源,如果應(yīng)用只有一個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)源,那么只需創(chuàng)建一個(gè)SessionFactory實(shí)例。當(dāng)SessionFactory對(duì)象創(chuàng)建后,該對(duì)象不和Configuration對(duì)象關(guān)聯(lián)。因此如果再修改Configuration對(duì)象包含的配置信息,不會(huì)對(duì)SessionFactory對(duì)象有任何影響。訪問(wèn)Hibernate的Session接口初始化過(guò)程結(jié)束后,就可以調(diào)用SessionFactory實(shí)例的openSession()方法來(lái)獲得Session實(shí)例,然后通過(guò)它執(zhí)行訪問(wèn)數(shù)據(jù)庫(kù)的操作。 Session接口提供了操縱數(shù)據(jù)庫(kù)的各種方法,如:save()方法:把Java對(duì)象保存數(shù)據(jù)庫(kù)中。update()方法:更新數(shù)據(jù)庫(kù)中的Java對(duì)象。delete()方法:把Java對(duì)象從數(shù)據(jù)庫(kù)中刪除。load()方法:從數(shù)據(jù)庫(kù)中加載Java對(duì)象。find()方法:從數(shù)據(jù)庫(kù)中查詢Java對(duì)象。Session是一個(gè)輕量級(jí)對(duì)象。通常將每一個(gè)Session實(shí)例和一個(gè)數(shù)據(jù)庫(kù)事務(wù)綁定,也就是說(shuō),每執(zhí)行一個(gè)數(shù)據(jù)庫(kù)事務(wù),都應(yīng)該先創(chuàng)建一個(gè)新的Session實(shí)例。如果事務(wù)執(zhí)行中出現(xiàn)異常,應(yīng)該撤銷事務(wù)。不論事務(wù)執(zhí)行成功與否,最后都應(yīng)該調(diào)用Session的close()方法,從而釋放Session實(shí)例占用的資源。以下代碼演示了用Session來(lái)執(zhí)行事務(wù)的流程,其中Transaction類用來(lái)控制事務(wù)。Sessionsession=factory.openSession();Transactiontx;try{//開(kāi)始一個(gè)事務(wù)tx=session.beginTransaction();//執(zhí)行事務(wù)//提交事務(wù)mit();}catch(Exceptione){//如果出現(xiàn)異常,就撤銷事務(wù)if(tx!=null)tx.rollback();throwe;}finally{//不管事務(wù)執(zhí)行成功與否,最后都關(guān)閉Sessionsession.close();}下圖為正常執(zhí)行數(shù)據(jù)庫(kù)事務(wù)(即沒(méi)有發(fā)生異常)的時(shí)序圖。BusinessService類提供了保存、刪除、查詢和更新Customer對(duì)象的各種方法。BusinessService類的main()方法調(diào)用test()方法,test()方法又調(diào)用以下方法:1.saveCustomer()方法該方法調(diào)用Session的save()方法,把Customer對(duì)象持久化到數(shù)據(jù)庫(kù)中。tx=session.beginTransaction();session.save(customer);mit();當(dāng)運(yùn)行session.save()方法時(shí),Hibernate執(zhí)行以下SQL語(yǔ)句:insertintoCUSTOMERS(ID,NAME,EMAIL,PASSWORD,PHONE,ADDRESS,SEX,IS_MARRIED,DESCRIPTION,IMAGE,BIRTHDAY,REGISTERED_TIME)Shanghai','M',0,'Iamveryhonest.',?,'1980-05-06',null)在test()方法中并沒(méi)有設(shè)置Customer對(duì)象的id屬性,Hibernate會(huì)根據(jù)映射文件的配置,采用increment標(biāo)識(shí)符生成器自動(dòng)以遞增的方式為OID賦值。在關(guān)的映射代碼如下:<idname="id"column="ID"type="long"><generatorclass="increment"/></id>在test()方法中也沒(méi)有設(shè)置Customer對(duì)象的registeredTime屬性,因此在以上insert語(yǔ)句中,REGISTERED_TIM£段的值為null。但由于REGISTERED_TIM字段的SQL類型為TIMESTAM類型,如果insert語(yǔ)句沒(méi)有為TIMESTAM類型的字段賦值,底層數(shù)據(jù)庫(kù)會(huì)自動(dòng)把當(dāng)前的系統(tǒng)時(shí)間賦值給 TIMESTAM類型的字段。因此,執(zhí)行完以上insert語(yǔ)句后,REGISTERED_TIM字段的值并不為null,而是插入該記錄時(shí)的系統(tǒng)時(shí)間。2.findAllCustomers()方法該方法調(diào)用Session的find()方法,查詢所有的Customer對(duì)象。tx=session.beginTransaction();Listcustomers=session.find("fromCasc");for(Iteratorit=customers.iterator();it.hasNext();){printCustomer(context,out,(Customer)it.next());}mit();Session的find()方法有好幾種重載形式,本例中傳遞的是字符串參數(shù)“fromCasc”,它使用的是Hibernate查詢語(yǔ)言。運(yùn)行session.find() 方法時(shí),Hibernate執(zhí)行以下SQL語(yǔ)句:select*fromCUSTOMERSorderbyNAMEasc;3.loadAndUpdateCustomer()方法該方法調(diào)用Session的load()方法,加載Customer對(duì)象,然后再修改Customer對(duì)象的屬性。tx=session.beginTransaction();Customerc=(Customer)session.load(Customer.class,customer_id);c.setAddress(address);mit();以上代碼先調(diào)用Session的load()方法,它按照參數(shù)指定的OID從數(shù)據(jù)庫(kù)中檢索出匹配的Customer對(duì)象,Hibernate會(huì)執(zhí)行以下SQL語(yǔ)句:select*fromCUSTOMERSwhereID=1;loadAndUpdateCustomer()方法接著修改Customer對(duì)象的address屬性。那么,Hibernate會(huì)不會(huì)同步更新數(shù)據(jù)庫(kù)中相應(yīng)的CUSTOMERS的記錄呢?答案是肯定的。Hibernate采用臟檢查機(jī)制,按照內(nèi)存中的Customer對(duì)象的狀態(tài)的變化,來(lái)同步更新數(shù)據(jù)庫(kù)中相關(guān)的數(shù)據(jù),Hibernate會(huì)執(zhí)行以下SQL語(yǔ)句:updateCUSTOMERSset"…ADDRESS="Beijing"…盡管只有Customer對(duì)象的address屬性發(fā)生了變化,但是Hibernate執(zhí)行的update語(yǔ)句中會(huì)包含所有的字段。在BusinessService類的test()方法中按如下方式調(diào)用loadAndUpdateCustomer()方法:saveCustomer(customer);loadAndUpdateCustomer(customer.getId(),"Beijing");以上代碼并沒(méi)有直接給customer對(duì)象的id屬性賦值,當(dāng)執(zhí)行saveCustomer(customer)方法時(shí),Session的save()方法把customer對(duì)象持久化到數(shù)據(jù)庫(kù)中,并自動(dòng)為id屬性賦值。4.printCustomer()方法該方法打印Customer對(duì)象的信息,它有三種重載形式。當(dāng)helloapp應(yīng)用作為獨(dú)立應(yīng)用程序運(yùn)行時(shí),將調(diào)用printCustomer(PrintStreamout,Customercustomer)方法,向控制臺(tái)輸出Customer信息;當(dāng)customerApp應(yīng)用作為JavaWeb應(yīng)用運(yùn)行時(shí),將調(diào)用printCustomer(ServletContextcontext,ServletOuputStreamout,Customercustomer)方法向Web客戶輸出Customer信息:privatevoidprintCustomer(ServletContextcontext,ServletOutputStreamout,Customercustomer)throwsException{//

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 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ì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論