Java EE程序設(shè)計(jì)教程-Hibernate高級(jí)編程_第1頁(yè)
Java EE程序設(shè)計(jì)教程-Hibernate高級(jí)編程_第2頁(yè)
Java EE程序設(shè)計(jì)教程-Hibernate高級(jí)編程_第3頁(yè)
Java EE程序設(shè)計(jì)教程-Hibernate高級(jí)編程_第4頁(yè)
Java EE程序設(shè)計(jì)教程-Hibernate高級(jí)編程_第5頁(yè)
已閱讀5頁(yè),還剩70頁(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高級(jí)編程Web應(yīng)用開(kāi)發(fā)技術(shù)(JavaEE)學(xué)習(xí)目標(biāo)首要目標(biāo)學(xué)習(xí)并掌握Hibernate核心類(lèi);理解掌握Hibernate主鍵生成策略;掌握Hibernate查詢(xún)語(yǔ)言;次要目標(biāo)理解復(fù)合主鍵理解動(dòng)態(tài)實(shí)體模型本章提綱6.1深入認(rèn)識(shí)Hibernate6.2批量查詢(xún)方法6.3Hibernate主鍵6.4動(dòng)態(tài)實(shí)體模型6.1深入認(rèn)識(shí)Hibernate6.1.1ConfigurationConfiguration是一個(gè)核心類(lèi),類(lèi)的路徑是org.hibernate.cfg.Configuration。通過(guò)前面的學(xué)習(xí)已經(jīng)知道,Configuration主要負(fù)責(zé)在Hibernate初始化時(shí)加載配置文件,讀取這些配置并創(chuàng)建一個(gè)SessionFactory對(duì)象。一個(gè)Configuration實(shí)例代表了一個(gè)應(yīng)用程序中Java類(lèi)型到數(shù)據(jù)庫(kù)映射的完整集合,映射定義則由不同的XML映射定義文件編譯而來(lái)。表6-1中列舉了Configuration類(lèi)所有的方法。6.1.1ConfigurationConfiguration使用configure()方法讀取配置文件,以及映射文件的裝載,可以通過(guò)以下幾種方式實(shí)現(xiàn)。(1)使用默認(rèn)的hibernate.cfg.xml文件

首先實(shí)例化一個(gè)Configuration對(duì)象Configurationmycfg=newConfiguration().configure();6.1.1Configuration在實(shí)例化mycfg對(duì)象的同時(shí)調(diào)用了不帶任何參數(shù)的configure()方法,Hibernate會(huì)在CLASSPATH下尋找hibernate.cfg.xml文件,將所有系統(tǒng)環(huán)境變量(System.getProperties())也添加到GLOBAL_PROPERTIES里面。如果hibernate.cfg.xml文件存在,系統(tǒng)還會(huì)驗(yàn)證一下這個(gè)文件配置的有效性,對(duì)于一些已經(jīng)不支持的配置參數(shù),系統(tǒng)將打印警告信息configure()方法首先會(huì)訪問(wèn)<session-factory>,并獲取該元素的name屬性。若非空,將用這個(gè)配置的值來(lái)覆蓋hibernate.session_factory_name的值。緊接著configure()方法會(huì)訪問(wèn)<session-factory>的子元素,然后依次訪問(wèn)<mapping>元素、<jcs-class-cache>元素以及<jcs-collection-cache>和<collection-cache>元素。其中必須通過(guò)配置<mapping>元素,configure()才能訪問(wèn)到系統(tǒng)定義的Java對(duì)象和關(guān)系數(shù)據(jù)庫(kù)表的映射文件(hbm.xml)。6.1.1Configuration(2)使用自定義配置文件Configuration對(duì)象也可以通過(guò)configure()方法使用不同的參數(shù)來(lái)調(diào)用自定義的配置文件或者使用以下方法。Filefile=newFile("E:\dev\testapp\etc\myhibernate.xml");Configurationmycfg=newConfiguration().configure(file);Configurationmycfg=newConfiguration().configure("myhibernate.xml");6.1.1Configuration(3)指定映射文件

可以直接實(shí)例化Configuration來(lái)獲取一個(gè)實(shí)例,并為他指定XML映射文件。如果映射文件在類(lèi)路徑中,則使用addResource()方法進(jìn)行加載。Configurationmycfg=newConfiguration().addResource("com/demo/hibernate/beans/User.hbm.xml");6.1.1Configuration(4)指定持久化類(lèi)實(shí)例化Configuration的時(shí)候,addClass()方法可以通過(guò)指定一個(gè)被映射的持久化類(lèi)來(lái)加載對(duì)應(yīng)的映射文件。Hibernate將會(huì)在類(lèi)路徑中需找名字為"/com/demo/hibernate/beans/User.hbm.xml"映射文件,消除了任何對(duì)文件名的硬編譯。與此同時(shí),還可以通過(guò)調(diào)用setProperty()方法指定配置屬性值。Configurationmycfg=newConfiguration().addClass(com.demo.hibernate.beans.User.class);Configurationmycfg=newConfiguration().addClass(com.demo.hibernate.beans.User.class).setProperty("hibernate.dialect","org.hibernate.dialect.MySQLInnoDBDialect").setProperty("hibernate.connection.datasource","java:comp/env/jdbc/test").setProperty("hibernate.order_update","true");6.1.2SessionFactorySessionFactory是一個(gè)工廠類(lèi),在Hibernate初始化階段負(fù)責(zé)創(chuàng)建Session對(duì)象。SessionFactory在Hibernate中實(shí)際上起到了一個(gè)緩沖區(qū)的作用,它緩沖了Hibernate自動(dòng)生成SQL語(yǔ)句和其他的映射數(shù)據(jù),還緩沖了一些將來(lái)有可能重復(fù)利用的數(shù)據(jù)。SessionFactory有以下特點(diǎn):它是線程安全的,這意味著它的同一個(gè)實(shí)例可以被應(yīng)用的多個(gè)線程共享。它是重量級(jí)的,不能隨意創(chuàng)建或銷(xiāo)毀它的實(shí)例。如果應(yīng)用只需要一個(gè)數(shù)據(jù)庫(kù),則只需要?jiǎng)?chuàng)建一個(gè)SessionFactory實(shí)例。如果需要訪問(wèn)多個(gè)數(shù)據(jù)庫(kù),則需要為每個(gè)數(shù)據(jù)庫(kù)創(chuàng)建一個(gè)單獨(dú)的SessionFactory實(shí)例。6.1.2SessionFactory在Hibernate4及其以上版本里新增了一個(gè)接口ServiceRegistry,所有基于Hibernate的配置或者服務(wù)都必須統(tǒng)一向這個(gè)ServiceRegistry注冊(cè)后才能生效。不難看出Hibernate4的配置入口不再是Configuration對(duì)象,而是ServiceRegistry對(duì)象,Configuration對(duì)象將通過(guò)ServiceRegistry對(duì)象獲取配置信息publicclassTest{privatestaticConfigurationconfiguration=null;privatestaticSessionFactorysessionFactory=null;privatestaticServiceRegistryserviceRegistry=null;publicstaticvoidmain(String[]args){try{configuration=newConfiguration().configure();serviceRegistry=newServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();sessionFactory=configuration.buildSessionFactory(serviceRegistry);}catch(HibernateExceptione){e.printStackTrace();}6.1.3SessionSession是Hibernate的核心接口,與數(shù)據(jù)庫(kù)之間發(fā)生的操作幾乎都與Session相關(guān)。然而Session并不是線程安全的,也就是說(shuō)當(dāng)多個(gè)線程同時(shí)使用一個(gè)Session實(shí)例進(jìn)行數(shù)據(jù)存取時(shí),將會(huì)導(dǎo)致數(shù)據(jù)錯(cuò)亂的問(wèn)題。Session的創(chuàng)建和銷(xiāo)毀不需要消耗太多的系統(tǒng)資源,所以在實(shí)際應(yīng)用中可以為每次事務(wù)處理單獨(dú)創(chuàng)建Session實(shí)例。與此同時(shí),每個(gè)Session實(shí)例也會(huì)有一個(gè)緩存,稱(chēng)為Hibernate第一級(jí)緩存,這個(gè)緩存只能被當(dāng)前工作單元訪問(wèn)。6.1.3Session1、Session的使用Session是由SessionFactory所創(chuàng)建,創(chuàng)建方法非常簡(jiǎn)單。創(chuàng)建好Session對(duì)象實(shí)例后,就可以使用它所具備的方法進(jìn)行多種數(shù)據(jù)庫(kù)操作。表6-3列出了Session所有的API,其中最主要的應(yīng)用包括以下幾個(gè)方法Configurationmycfg=newConfiguration().configure();SessionFactorysessionfactory=mycfg.buildSessionFactory();Sessionsession=sessionfactory.openSession();6.1.3Sessionget():從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)對(duì)象,不存在時(shí)返回nullload():從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)對(duì)象,不存在時(shí)拋出異常createQuery():根據(jù)條件查詢(xún)數(shù)據(jù)對(duì)象save():將對(duì)象保存到數(shù)據(jù)庫(kù)update():更新對(duì)象到數(shù)據(jù)庫(kù)delete():根據(jù)對(duì)象刪除數(shù)據(jù)庫(kù)數(shù)據(jù)6.1.3Session為了解決Session多線程之間數(shù)據(jù)共享的問(wèn)題,通常使用ThreadLoal類(lèi)來(lái)建立一個(gè)Session管理的輔助類(lèi),它能有效隔離執(zhí)行所使用的數(shù)據(jù)。ThreadLoal的使用方法有兩種:一種是自己實(shí)現(xiàn)ThreadLoal的子類(lèi),并重寫(xiě)initialValue()方法;另一種方法是定義一個(gè)靜態(tài)的ThreadLoal實(shí)例,通過(guò)使用set()方法來(lái)初始化這個(gè)線程局部變量的值。6.1.3SessionpublicclassHibernateUtil{privatestaticLoglog=LogFactory.getLog(HibernateUtil.class);privatestaticfinalSessionFactory.sessionFactory;static{try{//創(chuàng)建SessionFactorysessionFactory=newConfiguration().configure.buildSessionFactory();}catch(Throwex){//......}}publicstaticfinalThreadLocalthread_var=newThreadLocal();publicstaticSessioncurrentSession(){Seesions=thread_var.get();//如果這個(gè)線程為空,打開(kāi)一個(gè)新的Sessionif(s==null){s=sessionFactory.openSession();thead_var.get(s);}returns;}publicstaticvoidcloseSession(){Sessions=thread_var.get();if(s!=null)s.close();thread_var.set(null);}}6.1.3Session使用ThreadLocalthread_var=newThreadLocal()語(yǔ)句生成的thread_var變量是一個(gè)只在當(dāng)前線程有效的變量,也就是說(shuō)不同線程所擁有的thread_var變量是不一樣的。只要這個(gè)線程沒(méi)有結(jié)束,都可以通過(guò)thread_var變量的get()方法取出原先放入的對(duì)象。圖6-1ThreadLocal變量的使用6.1.3Session2、Session緩存Hibernate中緩存分為兩種:一級(jí)緩存(Session級(jí)別)和二級(jí)緩存(SessionFactory),如圖6-2所示。每一個(gè)Session實(shí)例都可以看作是一個(gè)容器,當(dāng)給save()、update()、saveOrUpdate()方傳遞一個(gè)對(duì)象時(shí),或使用load()、get()、list()、iterate()方法獲得一個(gè)對(duì)象時(shí),該對(duì)象都將被加入到Session的內(nèi)部緩存中。6.1.3SessionSession緩存作用減少程序訪問(wèn)數(shù)據(jù)庫(kù)的次數(shù)。很多對(duì)象數(shù)據(jù)不是經(jīng)常改變的,第一次訪問(wèn)這些對(duì)象時(shí),Hibernate會(huì)將它放入緩存中,以后只要這個(gè)對(duì)象沒(méi)有改變過(guò),訪問(wèn)這個(gè)對(duì)象時(shí)Hibernate就不會(huì)去數(shù)據(jù)庫(kù)中加載它,而是從內(nèi)存中直接返回。保證緩存中的數(shù)據(jù)與數(shù)據(jù)庫(kù)同步。緩存中的數(shù)據(jù)有可能與數(shù)據(jù)庫(kù)里的數(shù)據(jù)不一致,這時(shí)Hibernate會(huì)負(fù)責(zé)將緩存中的數(shù)據(jù)同步到數(shù)據(jù)庫(kù)中,這取決于FlushMode參數(shù)的取值。FlushMode.AUTO:調(diào)用Session的查詢(xún)方法時(shí),清理緩存,注意:這條規(guī)則必須保證顯式開(kāi)啟的事務(wù)中,對(duì)于outsideatransaction調(diào)用Smit()時(shí),清理緩存調(diào)用Session.flush()時(shí),清理緩存FlushMode.COMMIT:調(diào)用Session的查詢(xún)方法時(shí),不清理緩存調(diào)用Smit()時(shí),清理緩存調(diào)用Session.flush()時(shí),清理緩存FlushMode.NEVER(MANUAL):調(diào)用Session的查詢(xún)方法時(shí),不清理緩存調(diào)用Smit()時(shí),不清理緩存調(diào)用Session.flush()時(shí),清理緩存FlushMode.ALWAYS:測(cè)試未發(fā)現(xiàn)和auto有什么區(qū)別。調(diào)用Session的查詢(xún)方法時(shí),清理緩存,注意:這條規(guī)則必須保證顯式開(kāi)啟的事務(wù)中,對(duì)于outsideatransaction調(diào)用Smit()時(shí),清理緩存調(diào)用Session.flush()時(shí),清理緩存6.1.3Session一個(gè)事務(wù)中,對(duì)數(shù)據(jù)進(jìn)行了操作使其改變了值,這種變化往往不會(huì)立即傳遞到數(shù)據(jù)庫(kù),而是通過(guò)緩存機(jī)制先寫(xiě)入緩存。當(dāng)清理緩存時(shí),Hbernate會(huì)根據(jù)緩存中對(duì)象的狀態(tài)變化來(lái)同步更新數(shù)據(jù)庫(kù)。Sssion為應(yīng)用程序提供了兩個(gè)管理緩存的方法:evict(Obejcto):從緩存中清除參數(shù)指定的持久化對(duì)象clear():清空緩存中所有持久化對(duì)象6.2批量查詢(xún)方法在Hbernate中如果直接通過(guò)JDBCAPI查詢(xún)數(shù)據(jù)庫(kù),則必須在應(yīng)用程序中嵌入冗長(zhǎng)的SQL語(yǔ)句,這就顯得很麻煩。對(duì)于數(shù)據(jù)檢索,Hibernate提供了三種方式,分別是HQL、QBC和SQL檢索方式。對(duì)比這三種檢索方式,HQL是應(yīng)用得最為廣泛的一種。6.2.1HQLHQL(HibernateQueryLanguage)是一種面向?qū)ο蟮牟樵?xún)語(yǔ)言,它的語(yǔ)法與SQL有些相似。然而SQL操作的是數(shù)據(jù)庫(kù)中的表、視圖、字段等,HQL操作的是對(duì)象及對(duì)象的屬性。在應(yīng)用中,Hibernate會(huì)根據(jù)對(duì)象的映射文件將HQL轉(zhuǎn)換成可以在相應(yīng)的數(shù)據(jù)庫(kù)中執(zhí)行的SQL語(yǔ)句。HQL主要具有以下功能:6.2.1HQL在查詢(xún)語(yǔ)句中設(shè)定各種查詢(xún)條件。支持投影查詢(xún),即僅檢索出對(duì)象的部分屬性。支持分頁(yè)查詢(xún)。支持連接查詢(xún)。支持分組查詢(xún),允許使用having和groupby關(guān)鍵字。提供各種聚集函數(shù)如:sum()、min()和max()等。支持各種子查詢(xún),即嵌入式查詢(xún)。能夠調(diào)用自定義SQL函數(shù)。支持動(dòng)態(tài)綁定查詢(xún)參數(shù)。6.2.1HQL1、HQL的使用

先來(lái)看一個(gè)使用HQL語(yǔ)言進(jìn)行查詢(xún)的例子,檢索姓名為“Jerry”,并且年齡為29歲的Customer對(duì)象。//創(chuàng)建一個(gè)Query對(duì)象Queryquery=session.createQuery("fromCustomerascwhere=:customerName"+"andc.age=:customerAge");//動(dòng)態(tài)綁定參數(shù)query.setString("customerName","Jerry");query.setInteger("customerAge",29);//執(zhí)行查詢(xún)語(yǔ)句,返回查詢(xún)結(jié)果Listlist=query.list();6.2.1HQL使用HQL語(yǔ)句執(zhí)行查詢(xún)數(shù)據(jù)庫(kù)的主要操作步驟

(1)創(chuàng)建Query對(duì)象

(2)動(dòng)態(tài)綁定參數(shù)

(3)執(zhí)行查詢(xún)語(yǔ)句,返回結(jié)果6.2.1HQL2、HQL語(yǔ)法

除了Java類(lèi)與屬性的名稱(chēng)外,HQL查詢(xún)語(yǔ)句對(duì)大小寫(xiě)并不敏感。所以SeLeCT與sELEct以及SELECT是相同的,但是org.hibernate.eg.FOO并不等價(jià)于org.hibernate.eg.Foo并且foo.barSet也不等價(jià)于foo.BARSET,也就是說(shuō)對(duì)于對(duì)象以及對(duì)象屬性的名字是必須區(qū)分大小寫(xiě)的。HQL語(yǔ)法(1)from子句當(dāng)只想要查詢(xún)一個(gè)對(duì)象實(shí)例或者所有對(duì)象的集合,就可以使用from子句完成。Hibernate中最簡(jiǎn)單的查詢(xún)語(yǔ)句的形式如下:fromeg.Cat====select*fromt_catfromCatfromCatascatfromCatcatfromFormula,ParameterfromfromFormulaasform,ParameterasparamHQL語(yǔ)法(2)select子句當(dāng)查詢(xún)的內(nèi)容只是某個(gè)對(duì)象的某個(gè)屬性時(shí),只需要查詢(xún)其中的一部分,那么就可以使用select子句來(lái)查詢(xún)指定的屬性Stringhql="selectfromUseru";Queryquery=session.createQuery(hql);Iteratorit=query.iterator();while(it.hasNext()){System.out.println(it.next());}HQL語(yǔ)法(2)select子句對(duì)于一次需要查詢(xún)多個(gè)屬性值時(shí),查詢(xún)結(jié)果返回的方式就有點(diǎn)不同。Stringhql="select,u.passwordfromUseru";Queryquery=session.createQuery(hql);Iteratorit=query.iterator();while(it.hasNext()){Object[]result=(Object[])it.next();System.out.println(Object[0]);System.out.println(Object[1]);}HQL語(yǔ)法(3)條件查詢(xún)(where子句)選出的對(duì)象或者屬性數(shù)據(jù)有一些并不是我們想要的,這時(shí)就可以在查詢(xún)語(yǔ)句中通過(guò)where子句添加查詢(xún)條件。where子句的使用方法與SQL中的where非常相似,只不過(guò)HQL語(yǔ)言中的where子句使用的是對(duì)象的屬性,而SQL中的where操作的是表的字段名。Stringhql="fromUserasuwhere='Jerry'";Queryquery=session.createQuery(hql);Useru=(User)query.uniqueResult();HQL語(yǔ)法(3)條件查詢(xún)(where子句)HQL語(yǔ)言所支持的運(yùn)算符和含義以及使用方法與SQL幾乎完全一致,也可以在where子句中利用表達(dá)式設(shè)定查詢(xún)條件。運(yùn)算符含義=等于<>不等于>

大于<

小于<=小于等于isnull值為空isnotnull值非空in(value1,value2,…)等于列表中的某個(gè)值notin(value1,value2,…)不等于列表中的某個(gè)值betweenvalue1andvalue2大于等于value1并且小于等于value2notbetweenvalue1andvalue2小于value1或者大于value2like字符串匹配模式and邏輯與or邏輯或not邏輯非HQL語(yǔ)法(4)連接查詢(xún)SQL中兩張表之間可以通過(guò)兩個(gè)字段進(jìn)行相互關(guān)聯(lián),而在HQL中對(duì)象與對(duì)象之間也可以通過(guò)各自的某個(gè)屬性進(jìn)行關(guān)聯(lián)。HQL支持的連接類(lèi)型有內(nèi)連接(innerjoin)、左外連接(leftouterjoin),右外連接(rightouterjoin)和全連接(fulljoin)。fromCatascatinnerjoincat.mateasmatefromCatascatleftouterjoincat.kittensaskittenfromFormulaformfulljoinform.parameterparamHQL語(yǔ)法(5)聚集函數(shù)查詢(xún)?cè)谑褂肏QL進(jìn)行實(shí)體對(duì)象的查詢(xún)時(shí),還可以使用SQL中所支持的聚集函數(shù)。Hibernate中支持的聚集函數(shù)如表所示。聚集函數(shù)含義count()計(jì)算符合條件的記錄的條數(shù)avg()計(jì)算符合條件的平均值max()取最大值min()取最小值sum()計(jì)算符合條件的數(shù)值的和HQL語(yǔ)法(5)聚集函數(shù)查詢(xún)selectcount(*)fromStudentswheres.sdept='計(jì)算機(jī)系‘selectavg(s.age)fromStudentsselectmax(s.grade)fromScswhereo=1selectmin(s.grade)fromScswhereo=1selectsum(c.ccredit)fromCoursecHQL語(yǔ)法(6)分組與排序與SQL語(yǔ)句的使用類(lèi)似,HQL也支持groupby、having子句和orderby子句。一個(gè)返回聚集值的查詢(xún)可以按照一個(gè)返回的對(duì)象中的任何屬性(property)進(jìn)行分組,使用方法如下。selectcat.color,sum(cat.weight),count(cat)fromCatcatgroupbycat.colorselects.sdeptfromStudentswheres.ssex='M'groupbys.sdepthavingcount(*)>500fromStudentsorderbys.ageHQL語(yǔ)法(7)子查詢(xún)HQL支持在where子句中嵌套查詢(xún)語(yǔ)句,稱(chēng)為子查詢(xún)語(yǔ)句。一個(gè)子查詢(xún)語(yǔ)句必須被圓括號(hào)包圍起來(lái)fromStudentswheres.snoin(selectsnofromscwherecno='1')6.2.2CriteriaHibernate還支持QBC(QuerybyCriteria)的檢索方式,它也是一種面向?qū)ο蟮臋z索方式,將數(shù)據(jù)的查詢(xún)條件封裝成為一個(gè)對(duì)象。使用QBC檢索方式的就是Criteria接口,具體的查詢(xún)條件通過(guò)add()方法進(jìn)行添加。先來(lái)看一個(gè)例子,查詢(xún)姓名以字符“J”開(kāi)頭,且年齡大于20歲的Customer對(duì)象。Criteriacriteria=session.createCriteria(Customer.class);criteria.add(Restrictions.like("name","J%"));criteria.add(Restrictions.gt("age",20));Listresult=criteria.list();6.2.2Criteria使用Criteria進(jìn)行數(shù)據(jù)庫(kù)檢索的操作主要包括以下步驟調(diào)用Session對(duì)象的createCriteria()方法創(chuàng)建一個(gè)Criteria對(duì)象。設(shè)定查詢(xún)條件。可以通過(guò)Restrictions類(lèi)或者Expresssion類(lèi)創(chuàng)建查詢(xún)條件對(duì)象的實(shí)例。調(diào)用Criteria的list()方法執(zhí)行查詢(xún)語(yǔ)句。Criteria接口的方法Criteria接口用于執(zhí)行對(duì)象封裝的數(shù)據(jù)庫(kù)查詢(xún),其主要方法如表所示方法功能描述add()設(shè)置查詢(xún)條件,參數(shù)為Restrictions類(lèi)或者Expresssion類(lèi)創(chuàng)建的Criteria對(duì)象的實(shí)例。addOrder()設(shè)置結(jié)果集的排序規(guī)則,參數(shù)為一個(gè)Order對(duì)象的實(shí)例。createCriteria()創(chuàng)建Criteria對(duì)象。list()執(zhí)行數(shù)據(jù)庫(kù)查詢(xún),返回查詢(xún)結(jié)果。scroll()執(zhí)行數(shù)據(jù)庫(kù)查詢(xún),返回ScrollableResult類(lèi)型的結(jié)果。setFetchSize()設(shè)置獲取記錄的數(shù)目。setFirstResult()設(shè)置獲取第一個(gè)記錄的位置,從0開(kāi)始計(jì)算。setProjection()設(shè)置查詢(xún)Projecttion對(duì)象的實(shí)例。uniqueResult()得到唯一的結(jié)果對(duì)象的實(shí)例。Restrictions類(lèi)Restrictions類(lèi)主要用于生成Criteria接口執(zhí)行數(shù)據(jù)查詢(xún)時(shí)所需要的查詢(xún)條件,通過(guò)Restrictions類(lèi)可以構(gòu)建出常用的SQL運(yùn)算符。例如查詢(xún)年齡小于28歲的姓王的員工Criteriacriteria=session.createCriteria(Employee.class);criteria.add(Restrictions.and(Restrictions.lt("age",28),Restrictions.like("name","王%"));Listresult=criteria.list();Order類(lèi)使用Criteria接口執(zhí)行查詢(xún)時(shí)是通過(guò)Order類(lèi)來(lái)設(shè)置排序規(guī)則,在執(zhí)行中一般只用到Order類(lèi)的兩個(gè)靜態(tài)方法—asc()方法和desc()方法。這兩個(gè)方法的參數(shù)是需要進(jìn)行排序的屬性名,其中asc()進(jìn)行升序排列,desc()進(jìn)行降序排列。下面看一個(gè)使用Order類(lèi)設(shè)置排序規(guī)則的例子:查詢(xún)所有員工信息,按照年齡升序排列。Criteriacriteria=session.createCriteria(Employee.class);criteria.addOrder(Order.asc("age"));Listresult=criteria.list();Projections類(lèi)執(zhí)行查詢(xún)后可能只需要返回表中的指定列信息或者進(jìn)行統(tǒng)計(jì)查詢(xún)。Criteria接口提供setProjection(Projectionprojection)方法用于實(shí)現(xiàn)投影查詢(xún)操作。Projections類(lèi)用于幫助Criteria接口完成數(shù)據(jù)的分組查詢(xún)和統(tǒng)計(jì)功能,其包含的主要方法如表所示。方法功能描述avg()計(jì)算某個(gè)屬性的平均值count()統(tǒng)計(jì)某個(gè)屬性的數(shù)目max()取得某個(gè)屬性的最大值min()取得某個(gè)屬性的最小值sum()計(jì)算某個(gè)屬性的和rowCount()返回滿足條件的記錄的數(shù)目Projections類(lèi)第一個(gè)例子:查詢(xún)員工的name和age屬性第二個(gè)例子:查詢(xún)每個(gè)部門(mén)的員工數(shù)量。Criteriacriteria=session.createCriteria(Employee.class);criteria.setProjection(PjectionList().add(Pperty("name")).add(Pperty("age"));List<Object[]>result=criteria.list();Criteriacriteria=session.createCriteria(Employee.class);//對(duì)部門(mén)分組,統(tǒng)計(jì)id數(shù)量criteria.setProjection(PjectionList().add(Projections.groupProperty("department")).add(Projections.count("id")));//執(zhí)行查詢(xún)List<Object[]>result=criteria.list();6.3Hibernate主鍵Hibernate主鍵也叫做對(duì)象標(biāo)識(shí)符(ObjectIdentifier),簡(jiǎn)稱(chēng)OID。與關(guān)系數(shù)據(jù)庫(kù)表中主鍵的功能一樣,Hibernate賦予每個(gè)對(duì)象一個(gè)唯一的ID,以此區(qū)分不同的持久化對(duì)象。作為主鍵必須滿足以下條件:不允許為null。每條記錄或每個(gè)持久化對(duì)象具有唯一的主鍵值,不允許主鍵值重復(fù)。每條記錄或每個(gè)持久化對(duì)象的主鍵值永遠(yuǎn)不會(huì)改變。6.3.1主鍵生成策略Hibernate通過(guò)映射文件中的<id>元素下可選<generator>子元素控制主鍵的生成方式。在Hibernate中提供了幾種內(nèi)置的生成器,所有的生成器都實(shí)現(xiàn)net.sf.hibernate.id.IdentifierGenerator接口,某些應(yīng)用程序可以選擇自己特定的實(shí)現(xiàn)。下面介紹各種不同主鍵生成方式及其特點(diǎn)。6.3.1主鍵生成策略increment由Hibernate從數(shù)據(jù)庫(kù)中取出主鍵的最大值(每個(gè)session只取1次),以該值為基礎(chǔ),每次增量為1,在內(nèi)存中生成主鍵,不依賴(lài)于底層的數(shù)據(jù)庫(kù),因此可以跨數(shù)據(jù)庫(kù)。特點(diǎn):跨數(shù)據(jù)庫(kù),不適合多進(jìn)程并發(fā)更新數(shù)據(jù)庫(kù),適合單一進(jìn)程訪問(wèn)數(shù)據(jù)庫(kù),不能用于群集環(huán)境。<idname="id"column="ID"><generatorclass="increment"/></id>6.3.1主鍵生成策略identityidentity由底層數(shù)據(jù)庫(kù)生成標(biāo)識(shí)符,但這個(gè)主鍵必須設(shè)置為自增長(zhǎng),使用identity的前提條件是底層數(shù)據(jù)庫(kù)支持自動(dòng)增長(zhǎng)字段類(lèi)型。特點(diǎn):只能用在支持自動(dòng)增長(zhǎng)的字段數(shù)據(jù)庫(kù)中使用,如MySQL、SqlServer。<idname="id"column="ID"><generatorclass="identity"/></id>6.3.1主鍵生成策略nativenative由hibernate根據(jù)使用的數(shù)據(jù)庫(kù)自行判斷采用identity、hilo、sequence其中一種作為主鍵生成方式,靈活性很強(qiáng)。如果能支持identity則使用identity,如果支持sequence則使用sequence。特點(diǎn):根據(jù)數(shù)據(jù)庫(kù)自動(dòng)選擇,項(xiàng)目中如果用到多個(gè)數(shù)據(jù)庫(kù)時(shí),可以使用這種方式,使用時(shí)需要設(shè)置表的自增字段或建立序列,建立表等。<idname="id"column="ID"><generatorclass="native"/></id>6.3.1主鍵生成策略u(píng)uidUniversallyUniqueIdentifier,是指在一臺(tái)機(jī)器上生成的數(shù)字,它保證對(duì)在同一時(shí)空中的所有機(jī)器都是唯一的。標(biāo)準(zhǔn)的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx(8-4-4-4-12)其中每個(gè)

x

0-9

a-f

范圍內(nèi)的一個(gè)十六進(jìn)制的數(shù)字。特點(diǎn):uuid長(zhǎng)度大,占用空間大,跨數(shù)據(jù)庫(kù),不用訪問(wèn)數(shù)據(jù)庫(kù)就生成主鍵值,所以效率高且能保證唯一性,移植非常方便,推薦使用。<idname="id"column="ID"><generatorclass="uuid"/></id>6.3.1主鍵生成策略hilohilo(高低位方式highlow)是hibernate中最常用的一種生成方式,需要一張額外的表保存hi的值。保存hi值的表至少有一條記錄(只與第一條記錄有關(guān)),否則會(huì)出現(xiàn)錯(cuò)誤。特點(diǎn):跨數(shù)據(jù)庫(kù),hilo算法生成的標(biāo)志只能在一個(gè)數(shù)據(jù)庫(kù)中保證唯一。<idname="id"column="ID"><generatorclass="hilo"><paramname="table">hibernate_hilo</param>//指定保存hi值的表名<paramname="column">next_hi</param>//指定保存hi值的列名<paramname="max_lo">100</param>//指定低位的最大值</generator></id>6.3.1主鍵生成策略sequence采用數(shù)據(jù)庫(kù)提供的sequence機(jī)制生成主鍵,需要數(shù)據(jù)庫(kù)支持sequence。特點(diǎn):只能在支持序列的數(shù)據(jù)庫(kù)中使用,如Oracle。<generatorclass="sequence"><paramname="sequence">hibernate_id</param>//指定sequence的名稱(chēng)</generator>6.3.1主鍵生成策略seqhilo與hilo類(lèi)似,通過(guò)hi/lo算法實(shí)現(xiàn)的主鍵生成機(jī)制,只是將hilo中的數(shù)據(jù)表?yè)Q成了序列sequence,需要數(shù)據(jù)庫(kù)中先創(chuàng)建sequence,適用于支持sequence的數(shù)據(jù)庫(kù)。特點(diǎn):與hilo類(lèi)似,只能在支持序列的數(shù)據(jù)庫(kù)中使用。<idname="id"column="ID"><generatorclass="seqhilo"><paramname="sequence">hibernate_seq</param><paramname="max_lo">100</param></generator></id>6.3.1主鍵生成策略foreign使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的主鍵作為該對(duì)象主鍵。主要用于一對(duì)一關(guān)系中。特點(diǎn):很少使用,大多用在一對(duì)一關(guān)系中。<idname="id"column="ID"><generatorclass="foreign"><paramname="property">user</param></generator></id><one-to-onename="user"class="domain.User"constrained="true"/>6.3.1主鍵生成策略assigned主鍵由外部程序負(fù)責(zé)生成,在save()之前必須指定一個(gè)。Hibernate不負(fù)責(zé)維護(hù)主鍵生成。與Hibernate和底層數(shù)據(jù)庫(kù)都無(wú)關(guān),可以跨數(shù)據(jù)庫(kù)。在存儲(chǔ)對(duì)象前,必須要使用主鍵的setter方法給主鍵賦值。特點(diǎn):可以跨數(shù)據(jù)庫(kù),人為控制主鍵生成,應(yīng)盡量避免。<idname="id"column="ID"><generator

class="assigned"/></id>6.3.2復(fù)合主鍵使用兩個(gè)字段或兩個(gè)以上的字段作為主鍵,這種主鍵稱(chēng)為復(fù)合主鍵。使用復(fù)合主鍵,在定義映射文件時(shí)將持久化類(lèi)的多個(gè)屬性作為標(biāo)識(shí)符屬性,以維護(hù)對(duì)象和數(shù)據(jù)表記錄的對(duì)應(yīng)關(guān)系。Hibernate通過(guò)在映射文件中使用<composite-id>元素配置復(fù)合主鍵。復(fù)合主鍵主要有兩種形式:一種是基于持久化類(lèi)屬性的復(fù)合主鍵,另一種是基于主鍵類(lèi)的復(fù)合主鍵。6.3.2復(fù)合主鍵建立一張用戶表user(firstname,lastname,age),以firstname和lastname兩個(gè)字段作為復(fù)合主鍵。建表語(yǔ)句如下。createtableuser(firstnamevarchar(50)notnull,lastnamevarchar(50)notnull,ageintegerdefault0,primarykey(firstname,lastname))6.3.2復(fù)合主鍵1、基于持久化類(lèi)屬性的復(fù)合主鍵實(shí)體類(lèi)User中包含了復(fù)合主鍵屬性firstname、lastname。hibernate要求復(fù)合主鍵類(lèi)重寫(xiě)equals()和hashCode()方法,以作為不同數(shù)據(jù)間的識(shí)別的標(biāo)志。User.java代碼如下publicclassUserimplementsSerializable{privateStringfirstname;privateStringlastname;privateintage;publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}6.3.2復(fù)合主鍵1、基于持久化類(lèi)屬性的復(fù)合主鍵實(shí)體類(lèi)User中包含了復(fù)合主鍵屬性firstname、lastname。hibernate要求復(fù)合主鍵類(lèi)重寫(xiě)equals()和hashCode()方法,以作為不同數(shù)據(jù)間的識(shí)別的標(biāo)志。User.java代碼如下publicStringgetFirstname(){returnfirstname;}publicvoidsetFirstname(Stringfirstname){this.firstname=firstname;}publicStringgetLastname(){returnlastname;}publicvoidsetLastname(Stringlastname){this.lastname=lastname;}6.3.2復(fù)合主鍵1、基于持久化類(lèi)屬性的復(fù)合主鍵實(shí)體類(lèi)User中包含了復(fù)合主鍵屬性firstname、lastname。hibernate要求復(fù)合主鍵類(lèi)重寫(xiě)equals()和hashCode()方法,以作為不同數(shù)據(jù)間的識(shí)別的標(biāo)志。User.java代碼如下publicbooleanequals(Objectobj){if(!(objinstanceofUser)){returnfalse;}else{Useruser=(User)obj;returnnewEqualsBuilder().appendSuper(super.equals(obj)).append(this.firstname,user.firstname).append(this.lastname,user.lastname).isEquals();}}6.3.2復(fù)合主鍵1、基于持久化類(lèi)屬性的復(fù)合主鍵實(shí)體類(lèi)User中包含了復(fù)合主鍵屬性firstname、lastname。hibernate要求復(fù)合主鍵類(lèi)重寫(xiě)equals()和hashCode()方法,以作為不同數(shù)據(jù)間的識(shí)別的標(biāo)志。User.java代碼如下publicinthashCode(){returnnewHashCodeBuilder(-528253723,-475504089).appendSuper(super.hashCode()).append(this.firstname).append(this.lastname).toHashCode();}}6.3.2復(fù)合主鍵1、基于持久化類(lèi)屬性的復(fù)合主鍵使用Hibernate建立user表與User類(lèi)之間的映射,與之對(duì)應(yīng)的映射文件User.hbm.xml關(guān)鍵代碼配置如下:<classname="User"table="user"><composite-id><key-propertyname="lastname"column="lastname"type="string"/><key-propertyname="firstname"column="firstname"type="string"/></composite-id><propertyname="Age"column="age"type="integer"not-null="false"length="10"/></class>6.3.2復(fù)合主鍵1、基于持久化類(lèi)屬性的復(fù)合主鍵通過(guò)composite-id節(jié)點(diǎn)聲明了一個(gè)復(fù)合主鍵,是由“firstname"和"lastname"組成。元素<key-property>將User類(lèi)的主鍵屬性和數(shù)據(jù)表user的主鍵字段一一對(duì)應(yīng)。緊接著可以利用Session.load()方法,將User類(lèi)對(duì)象本身作為查詢(xún)條件進(jìn)行數(shù)據(jù)庫(kù)操作。Useruser=newUser();user.setFirstname("zhang");user.setLastname("san");user=(User)session.load(User.class,user);System.out.println("age:"+user.getAge());6.3.2復(fù)合主鍵基于持久化類(lèi)的復(fù)合主鍵映射時(shí),需要注意以下幾個(gè)問(wèn)題持久化類(lèi)本身就是自己的主鍵。持久化類(lèi)必須實(shí)現(xiàn)java.io.Serializable接口。為了實(shí)現(xiàn)對(duì)象標(biāo)識(shí)的比較,需要重寫(xiě)hashCode()方法和equals()方法。裝載對(duì)象是,需要先初始化持久化類(lèi)的實(shí)例,填充主鍵屬性,再用session裝載對(duì)象。6.3.2復(fù)合主鍵

2、基于主鍵類(lèi)的復(fù)合主鍵可以將主鍵與邏輯加以分離,以一個(gè)單獨(dú)的主鍵類(lèi)對(duì)復(fù)合主鍵進(jìn)行描述。現(xiàn)在把User中的firstname和lastname提取到一個(gè)獨(dú)立的主鍵類(lèi)UserPK中。UserPK.java代碼如下:6.3.2復(fù)合主鍵

2、基于主鍵類(lèi)的復(fù)合主鍵publicclassUserPKimplementsSerializable{privateStringfirstname;privateStringlastname;publicStringgetFirstname(){returnfirstname;}publicvoidsetFirstname(Stringfirstname){this.firstname=firstname;}publicStringgetLastname(){returnlastname;}publicvoidsetLastname(Stringlastname){this.lastname=lastname;}//此處省略hashCode()和equals()方法}6.3.2復(fù)合主鍵修改User.java代碼如下:publicclassUserimplementsSerializable{privateUserPKuserPk;privateintage;publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicUserPKgetUserPk(){returnuserPk;}publicvoidsetUserPk(UserPKuserPk){this.userPk=userPk;}}6.3.2復(fù)合主鍵此時(shí)User類(lèi)里不再有firstname和lastname兩個(gè)主鍵屬性,而是由主鍵類(lèi)UserPK進(jìn)行管理。持久化類(lèi)User使用主鍵類(lèi)UserPK屬性作為標(biāo)識(shí)符,唯一的識(shí)別系統(tǒng)中的對(duì)象。修改User.hbm.xml映射文件中的<composite-id>節(jié)點(diǎn),具體如下。<composite-idname="userPk"class="UserPK"><key-propertyname="lastname"column="lastname"type="string"/><key-propertyname="firstname"column="firstname"type="string"/></composite-id><propertyn

溫馨提示

  • 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)論