




已閱讀5頁(yè),還剩17頁(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)介
JPA開(kāi)發(fā)文檔1. 發(fā)展中的持久化技術(shù)11.1 JDBC11.2關(guān)系對(duì)象映射(Object Relational Mapping,ORM)21.3 Java數(shù)據(jù)對(duì)象(Java Data Object,JDO)21.4 Java Persistence API(JPA)22. JPA體系架構(gòu)3清單1在非Java EE環(huán)境使用JPA接口的例子5清單2在容器中運(yùn)行的JPA例子53. Entity Bean63.1定義對(duì)Entity中屬性變量的訪問(wèn)63.2主鍵和實(shí)體標(biāo)識(shí)(Primary Key and Entity Identity)84. EntityManager94.1配置和獲得EntityManager94.2 Entity的生命周期和狀態(tài)104.3持久化Entity(Persist)114.4獲取Entity134.5更新Entity134.6刪除Entity144.7脫離/附合(Detach/Merge)145. JPA Query155.1 Query接口155.2簡(jiǎn)單查詢(xún)165.3使用參數(shù)查詢(xún)175.4排序(order by)175.5查詢(xún)部分屬性185.6查詢(xún)中使用構(gòu)造器(Constructor)185.7聚合查詢(xún)(Aggregation)195.8關(guān)聯(lián)(join)205.9比較Entity225.10批量更新(Batch Update)225.11批量刪除(Batch Remove)221. 發(fā)展中的持久化技術(shù)1.1 JDBC很多企業(yè)應(yīng)用的開(kāi)發(fā)者選擇使用 JDBC管理關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)。JDBC支持處理大量的數(shù)據(jù),能夠保證數(shù)據(jù)的一致性,支持信息的并發(fā)訪問(wèn),提供 SQL查詢(xún)語(yǔ)言查找數(shù)據(jù)。JDBC所使用的關(guān)系模型不是為保存對(duì)象而設(shè)計(jì)的,因此迫使開(kāi)發(fā)者選擇在處理持久數(shù)據(jù)時(shí)放棄面向?qū)ο缶幊?,或者自己去開(kāi)發(fā)將面向?qū)ο筇匦裕ū热纾侯?lèi)之間的繼承)和關(guān)系型數(shù)據(jù)庫(kù)進(jìn)行映射的專(zhuān)有解決方案。1.2關(guān)系對(duì)象映射(Object Relational Mapping,ORM)ORM是目前完成對(duì)象和關(guān)系數(shù)據(jù)表之間的映射最好的一種技術(shù), 這些 ORM框架處理對(duì)象和關(guān)系數(shù)據(jù)庫(kù)之間的協(xié)調(diào)工作,將開(kāi)發(fā)者從這部分工作中解脫出來(lái),集中精力處理對(duì)象模型。阻礙 ORM發(fā)展的問(wèn)題是,現(xiàn)有的每一種 ORM產(chǎn)品都有自己特有的 API,開(kāi)發(fā)者只能將自己的代碼綁定到某一個(gè)框架提供商的接口上,這種狀況形成了廠商鎖定,意味著一旦該框架提供商無(wú)法解決系統(tǒng)中出現(xiàn)的嚴(yán)重錯(cuò)誤,或者因?yàn)槠渌脑蜣D(zhuǎn)而采用其它的框架,將會(huì)給開(kāi)發(fā)者的企業(yè)應(yīng)用帶來(lái)極大的困難,唯一的解決辦法是重寫(xiě)所有的持久化代碼。1.3 Java數(shù)據(jù)對(duì)象(Java Data Object,JDO)JDO是 Java EE標(biāo)準(zhǔn)中另外一個(gè)支持管理持久化數(shù)據(jù)的規(guī)范,JDO規(guī)范使用和 JPA非常類(lèi)似的 API,只是通常是通過(guò) JCA技術(shù)集成到應(yīng)用服務(wù)器上。但是 JDO是針對(duì)輕量級(jí)容器而設(shè)計(jì)的,不能夠支持容器級(jí)別的聲明式安全、事務(wù)特性,也無(wú)法對(duì)遠(yuǎn)程方法調(diào)用提供支持。1.4 Java Persistence API(JPA)EJB 3.0規(guī)范由三部分組成:EJB3.0 Simplified API、EJB核心規(guī)范(EJB Core Contracts and Requirements)和 JPA(Java Persistence API)。JPA規(guī)范部分詳細(xì)的介紹了 JPA中實(shí)體 Bean的定義,并介紹了實(shí)體 Bean支持的注釋、全新的查詢(xún)語(yǔ)言、實(shí)體管理接口、容器實(shí)現(xiàn)規(guī)范等內(nèi)容。JPA標(biāo)準(zhǔn)制定過(guò)程中充分吸收了目前已經(jīng)出現(xiàn)的所有持久化技術(shù)的所有優(yōu)點(diǎn),摒棄了它們存在的局限,使 JPA在簡(jiǎn)單易用、查詢(xún)能力等方面表現(xiàn)突出。 標(biāo)準(zhǔn)化JPA是 JCP組織發(fā)布的 Java EE標(biāo)準(zhǔn)之一,因此任何聲稱(chēng)符合 JPA標(biāo)準(zhǔn)的框架都遵循同樣的架構(gòu),提供相同的訪問(wèn) API,這保證了基于 JPA開(kāi)發(fā)的企業(yè)應(yīng)用能夠經(jīng)過(guò)少量的修改就能夠在不同的 JPA框架下運(yùn)行。 對(duì)容器級(jí)特性的支持JPA框架中支持大數(shù)據(jù)集、事務(wù)、并發(fā)等容器級(jí)事務(wù),這使得JPA超越了簡(jiǎn)單持久化框架的局限,在企業(yè)應(yīng)用發(fā)揮更大的作用。 簡(jiǎn)單易用,集成方便JPA的主要目標(biāo)之一就是提供更加簡(jiǎn)單的編程模型:在 JPA框架下創(chuàng)建實(shí)體和創(chuàng)建 Java類(lèi)一樣簡(jiǎn)單,沒(méi)有任何的約束和限制,只需要使用 javax.persistence.Entity 進(jìn)行注釋?zhuān)籎PA的框架和接口也都非常簡(jiǎn)單,沒(méi)有太多特別的規(guī)則和設(shè)計(jì)模式的要求,開(kāi)發(fā)者可以很容易的掌握。JPA基于非侵入式原則設(shè)計(jì),因此可以很容易的和其它框架或者容器集成。 可媲美JDBC的查詢(xún)能力JPA定義了獨(dú)特的 JPQL(Java Persistence Query Language),JPQL是 EJB QL的一種擴(kuò)展,它是針對(duì)實(shí)體的一種查詢(xún)語(yǔ)言,操作對(duì)象是實(shí)體,而不是關(guān)系數(shù)據(jù)庫(kù)的表,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL才能夠提供的高級(jí)查詢(xún)特性,甚至還能夠支持子查詢(xún)。 支持面向?qū)ο蟮母呒?jí)特性JPA中能夠支持面向?qū)ο蟮母呒?jí)特性,比如類(lèi)之間的繼承、多態(tài)和類(lèi)之間的復(fù)雜關(guān)系,這樣的支持能夠讓開(kāi)發(fā)者最大限度的使用面向?qū)ο蟮哪P驮O(shè)計(jì)企業(yè)應(yīng)用,而不需要自行處理這些特性在關(guān)系數(shù)據(jù)庫(kù)的持久化。支持內(nèi)容:JDBCORMJDOEJB 3(JPA)Java對(duì)象NoYesYesYes高級(jí)OO原理NoYesYesYes事務(wù)完整性YesYesYesYes并發(fā)YesYesYesYes大數(shù)據(jù)集YesYesYesYes現(xiàn)有 SchemaYesYesYesYes關(guān)系型和非關(guān)系型數(shù)據(jù)存儲(chǔ)NoNoYesNo查詢(xún)YesYesYesYes嚴(yán)格的標(biāo)準(zhǔn)/可移植NoNoYesYes簡(jiǎn)單易用YesYesYesYes表1持久化技術(shù)的優(yōu)缺點(diǎn)2. JPA體系架構(gòu)JPA中定義一套類(lèi)和接口用于實(shí)現(xiàn)持久化管理和對(duì)象/關(guān)系的映射,下面這張圖中顯示了 JPA的主要組件以及它們之間的相互關(guān)系。圖1 JPA主要組件和相互關(guān)系 EntityManagerFactory EntityManagerFactory 是 EntityManager 的工廠類(lèi),負(fù)責(zé)創(chuàng)建 EntityManager 對(duì)象。 EntityManager EntityManager 是 JPA應(yīng)用中使用的基本對(duì)象,通過(guò)它提供的相應(yīng)方法可以管理持久化對(duì)象,也可以新建或者刪除持久化對(duì)象。EntityManager還負(fù)責(zé)創(chuàng)建Query實(shí)例。在容器外使用時(shí),EntityManagerFactory和EntityManager之間是一對(duì)一的關(guān)系。 Entity EntityTransaction提供Entity操作時(shí)需要的事務(wù)管理,和 EntityManager 是一對(duì)一的關(guān)系。在查詢(xún)操作時(shí)不需要使用 EntityTransaction,而在對(duì)象持久化、狀態(tài)更新、對(duì)象刪除等情況下則必須使用顯式的使用 EntityTransaction 的相關(guān)方法管理事務(wù)。 Query Query是查詢(xún)實(shí)體的接口,Query對(duì)象可以從 EntityManager 中獲得。根據(jù) EJB 3.0規(guī)范中的描述,Query接口需要同時(shí)支持JPQL和原生態(tài)SQL兩種語(yǔ)法。 Persistence Persistence是一個(gè)工具類(lèi),負(fù)責(zé)根據(jù)配置文件提供的參數(shù)創(chuàng)建EntityManagerFactory對(duì)象。 下面的代碼演示了如何通過(guò) JPA提供的接口和 JPQL查詢(xún)語(yǔ)言完成實(shí)體查詢(xún)和更新的例子,例子中的代碼假定運(yùn)行在非 Java EE環(huán)境中。 清單1在非Java EE環(huán)境使用JPA接口的例子EntityManagerFactory factory = Persistence.createEntityManagerFactory (“mysql”); /從 EntityManagerFactory實(shí)例 factory中獲取 EntityManagerEntityManager em = factory.createEntityManager(PersistenceContextType.EXTENDED); /實(shí)體的更新需要在事務(wù)中運(yùn)行EntityTransaction tx = em.getTransaction ();tx.begin (); /查找所有公司中的女性雇員Query query = em.createQuery (select e from Employee e where e.sex = femail);List results = query.getResultList (); /給所有女性雇員增加半天假期for (Object res : results) Employee emp = (Employee) res; emp.setHoliday (emp.getHoliday () +0.5); /提交事務(wù)(持久化所有更新)mit ();em.close ();factory.close (); 下面的代碼顯示了在 EJB容器中開(kāi)發(fā) JPA應(yīng)用時(shí)的接口使用情況,由于容器中的 EntityManager 是注入的,事務(wù)也是聲明式的,因此在容器中完成上面的業(yè)務(wù)邏輯要簡(jiǎn)單得多。 清單2在容器中運(yùn)行的JPA例子/*在容器中運(yùn)行JPA應(yīng)用時(shí),EntityManager接口的實(shí)例”em”*是通過(guò)Resource注釋注入的。事務(wù)也通常是聲明式的。*/查找所有公司中的女性雇員Query query = em.createQuery (select e from Employee e where e.sex = femail);List results = query.getResultList (); /給所有女性雇員增加半天假期for (Object res : results) Employee emp = (Employee) res; emp.setHoliday (emp.getHoliday () +0.5); 3. Entity BeanEJB3 Entity可以是很簡(jiǎn)單的java bean,只要批注了Entity或者在xml配置中作了說(shuō)明,就被做一個(gè)可持久化的Entity處理。 但還是需要遵行一定的規(guī)則: Entity類(lèi)必須要有一個(gè)無(wú)參數(shù)的public或者protected的Constructor。 如果在應(yīng)用中需要將該Entity類(lèi)分離出來(lái)在分布式環(huán)境中作為參數(shù)傳遞,該Entity Class需要實(shí)現(xiàn)java.io.Serialzable接口。 Entity類(lèi)不可以是final,也不可有final的方法。 abstract類(lèi)和Concrete實(shí)體類(lèi)都可以作為Entity類(lèi)。 Entity類(lèi)中的屬性變量不可以是public。Entity類(lèi)的屬性必須通過(guò)getter/setter或者其他的商業(yè)方法獲得。3.1定義對(duì)Entity中屬性變量的訪問(wèn)在絕大部分的商業(yè)應(yīng)用,開(kāi)發(fā)人員都可以忽略這部分無(wú)需關(guān)心。但如果你需要編寫(xiě)復(fù)雜的Entity類(lèi)的話,你需要了解這個(gè)部分。復(fù)雜的Entity類(lèi)是指在Entity類(lèi)的getter/setter和商業(yè)方法中包含比較復(fù)雜的業(yè)務(wù)邏輯而不是僅僅返回/符值某個(gè)屬性。在大部分的情況下,我們都建議使Entity類(lèi)中setter/getter中的邏輯盡可能簡(jiǎn)單,除了必要的校驗(yàn)符值外,不要包含復(fù)雜的業(yè)務(wù)邏輯,例如對(duì)關(guān)聯(lián)的其他Entity類(lèi)進(jìn)行操作。但有些情況下,我們還是需要在Entity類(lèi)的setter/getter方法中包含商業(yè)邏輯。這時(shí)候,采用何種屬性訪問(wèn)方式就可能會(huì)影響代碼的性能甚至是邏輯正確產(chǎn)生影響。EJB3持久化規(guī)范中,在默認(rèn)情況下所有的屬性都會(huì)自動(dòng)的被持久化,除非屬性變量用Transient元數(shù)據(jù)進(jìn)行了標(biāo)注。針對(duì)可持久化屬性定義了兩種屬性訪問(wèn)方式(access): FIELD和PROPERTY。 如果采用access=FIELD, EJB3 Persistence運(yùn)行環(huán)境直接訪問(wèn)對(duì)象的屬性變量,而不是通過(guò)getter。這種訪問(wèn)方式也不要求每個(gè)屬性必須有g(shù)etter/setter。如果需要在getter中包含商業(yè)邏輯,應(yīng)該采用access=FIELD的方式。 如果采用access=PROPERTY, EJB3 Persistence運(yùn)行環(huán)境將通過(guò)Entity類(lèi)上的getter來(lái)訪問(wèn)對(duì)象的屬性變量,這就要求每個(gè)屬性變量要有g(shù)etter/setter方法。在EJB3中,默認(rèn)的屬性訪問(wèn)方式是PROPERTY。access=PROPERTY時(shí)getter/setter的邏輯應(yīng)該盡量簡(jiǎn)單。 規(guī)范中access方式還有多一層含義。就是采用access=FIELD時(shí),元數(shù)據(jù)應(yīng)該批注在屬性上。 Id(generate=GeneratorType.NONE) private int id; private String foo; /* * The entity class must have a no-arg constructor. */ public HelloEntityBean() public int getId() return id; 采用access=PROPERTY(默認(rèn)方式)時(shí),元數(shù)據(jù)應(yīng)該批注在對(duì)應(yīng)屬性變量的getter上。 private int id;private String foo; /* * The entity class must have a no-arg constructor.*/public HelloEntityBean() Id(generate=GeneratorType.NONE)public int getId() return id; Entity類(lèi)中的屬性變量可以是以下數(shù)據(jù)類(lèi)型: 原始數(shù)據(jù)類(lèi)型和他們的對(duì)象類(lèi)型 java.lang.String java.math.BigInteger java.math.BigDecimal java.util.Date java.util.Calendar java.sql.Date java.sql.Time java.sql.Timestamp byte Byte char Character enums Entity類(lèi) 嵌入實(shí)體類(lèi)(embeddable classes)還可以是以下集合類(lèi)型: java.util.Collection和它的實(shí)體類(lèi) java.util.Set和它的實(shí)體類(lèi) java.util.List和它的實(shí)體類(lèi) java.util.Map和它的實(shí)體類(lèi) 3.2主鍵和實(shí)體標(biāo)識(shí)(Primary Key and Entity Identity)每個(gè)Entity類(lèi)都必須有一個(gè)主鍵。在EJB3中定義了兩種主鍵:鍵單主鍵和復(fù)合主鍵。 簡(jiǎn)單主鍵必須對(duì)應(yīng)Entity中的一個(gè)屬性變量(Instance Variable),而該屬性對(duì)應(yīng)數(shù)據(jù)庫(kù)表中的一列。使用簡(jiǎn)單主鍵,我們只需要用Id元數(shù)據(jù)對(duì)一個(gè)屬性變量或者她的getter方法進(jìn)行批注。當(dāng)我們需要使用一個(gè)或多個(gè)屬性變量(表中的一列或多列)聯(lián)合起來(lái)作為主鍵,我們需要使用復(fù)合主鍵。復(fù)合主鍵要求我們編寫(xiě)一個(gè)復(fù)合主鍵類(lèi)( Composite Primary Key Class )。復(fù)合主鍵類(lèi)需要符合以下一些要求: 復(fù)合主鍵類(lèi)必須是public和具備一個(gè)沒(méi)有參數(shù)的constructor 復(fù)合主鍵類(lèi)的每個(gè)屬性變量必須有g(shù)etter/setter,如果沒(méi)有,每個(gè)屬性變量則必須是public或者protected 復(fù)合主鍵類(lèi)必須實(shí)現(xiàn)java.io.serializable 復(fù)合主鍵類(lèi)必須實(shí)現(xiàn)equals()和hashcode()方法 復(fù)合主鍵類(lèi)中的主鍵屬性變量的名字必須和對(duì)應(yīng)的Entity中主鍵屬性變量的名字相同 一旦主鍵值設(shè)定后,不要修改主鍵屬性變量的值 復(fù)合主鍵的例子。Entity類(lèi)Person,它的主鍵屬性變量是firstName和lastName。 Id private String firstName; Id private String lastName; public Person() Person的復(fù)合主鍵類(lèi): public class PersonPK implements java.io.Serializable private String firstName; private String lastName; public PersonPK() public String getFirstName() return firstName; public void setFirstName(String firstName) this.firstName = firstName; public String getLastName() return lastName; public void setLastName(String lastName) this.lastName = lastName; 4. EntityManager對(duì)Entity進(jìn)行操作的API都設(shè)計(jì)在javax.persistence.EntityManager接口上。EntityManager,顧名思義是管理所有EJB 3運(yùn)行環(huán)境中的所有Entity。 EntityManager根據(jù)運(yùn)行的環(huán)境不同分為容器管理的EntityManager和應(yīng)用管理的EntityManager。 4.1配置和獲得EntityManager在J2SE環(huán)境中,EJB3定義了一個(gè)javax.persistence.Persistence類(lèi)用于啟動(dòng)EJB3運(yùn)行環(huán)境。要獲得EntityManager,首先需要通過(guò)javax.persistence.Persistence獲得EntityManagerFactory,然后調(diào)用EntityManagerFactory.createEntityManager()方法獲得。 /獲得默認(rèn)當(dāng)前的EntityManagerFactory final EntityManagerFactory emf = Persistence.createEntityManagerFactory(); final EntityManager entityManager = emf.createEntityManager(); 當(dāng)調(diào)用Persistence.createEntityManagerFactory()的時(shí)候,Persistence會(huì)做以下的步驟: 搜索當(dāng)前jar包的META-INFO/persistence.xml配置文件 如果沒(méi)有在META-INFO下找到persistence.xml,搜索當(dāng)前線程的ContextClassLoader中的persistence.xml 根據(jù)獲得的persistence.xml初始化EntityManagerFactory4.2 Entity的生命周期和狀態(tài)在EJB3中定義了四種Entity的狀態(tài): 新實(shí)體(new)。Entity由應(yīng)用產(chǎn)生,和EJB3 Persistence運(yùn)行環(huán)境沒(méi)有聯(lián)系,也沒(méi)有唯一的標(biāo)示符(Identity)。 持久化實(shí)體(managed)。新實(shí)體和EJB3 Persistence運(yùn)行環(huán)境產(chǎn)生關(guān)聯(lián)(通過(guò)persist(), merge()等方法),在EJB3 Persistence運(yùn)行環(huán)境中存在和被管理,標(biāo)志是在EJB3 Persistence運(yùn)行環(huán)境中有一個(gè)唯一的標(biāo)示(Identity)。 分離的實(shí)體(detached)。Entity有唯一標(biāo)示符,但它的標(biāo)示符不被EJB3 Persistence運(yùn)行環(huán)境管理,同樣的該Entity也不被EJB3 Persistence運(yùn)行環(huán)境管理。 刪除的實(shí)體(removed)。Entity被remove()方法刪除,對(duì)應(yīng)的紀(jì)錄將會(huì)在當(dāng)前事務(wù)提交的時(shí)候從數(shù)據(jù)庫(kù)中刪除。 圖2 狀態(tài)的轉(zhuǎn)化4.3持久化Entity(Persist) final EntityManagerFactory emf = Persistence.createEntityManagerFactory(); final EntityManager entityManager = emf.createEntityManager(); final HelloEntityBean hello = new HelloEntityBean( 1, foo ); EntityTransaction trans = entityManager.getTransaction(); trans.begin(); /持久化hello,在此操作之前hello的狀態(tài)為new entityManager.persist( hello ); /這時(shí)hello的狀態(tài)變?yōu)閙anaged mit(); entityManager.close(); /這時(shí)hellow的狀態(tài)變?yōu)閐etached. 當(dāng)保存一個(gè)Entity時(shí),以該對(duì)象為根對(duì)象的整個(gè)對(duì)象圖都會(huì)自動(dòng)的被保存。但在EJB3中,我們?nèi)匀豢梢酝ㄟ^(guò)關(guān)系元數(shù)據(jù)(比如OneToOne,OneToMany)的cascade屬性來(lái)精確定義保存的級(jí)聯(lián)行為。 下面我們來(lái)看看不同的cascade屬性的區(qū)別。 不配置cascade的情況下,EJB3 Persistence運(yùn)行環(huán)境默認(rèn)不會(huì)采用Persistence by reachability。 public class Father Id int id String name; / OneToOne沒(méi)有配置cascade屬性,因此默認(rèn)不會(huì)使用Persistence by reachablity OneToOne Son mySon public Father( int id, String name, Son mySon ) this.id = id; = name; this.mySon = mySon; 現(xiàn)在來(lái)保存一個(gè)Father和Son。 final EntityManager manager = emf.createEntityManager(); manager.getTransaction().begin; Son mySon = new Son(); Father = new Father( 1, father mySon ); /保存Father manager.persist( father ); /由于OneToOne關(guān)系中沒(méi)有配置casacade屬性,father關(guān)聯(lián)的mySon不會(huì)被自動(dòng)保存,需要分別保存 manager.persist( mySon ); manager.getTransaction().commit(); manager.close(); 現(xiàn)在我們配置casacde=CascadeType.ALL public class Father Id int id String name; / OneToOne配置cascade=CascadeType.ALL,配置cascade=CascadeType.PERSIT也對(duì)persist操作也可以獲得同樣的效果。 / CascadeType.ALL包含CascadeType.PERSIST。 OneToOne(cascade=CascadeType.ALL) Son mySon public Father( int id, String name, Son mySon ) this.id = id; this.mySon = mySon; = name; 在代碼中同樣持久化Father和mySon。 final EntityManager manager = emf.createEntityManager(); manager.getTransaction().begin; Son mySon = new Son(); Father = new Father( 1, mySon ); /保存Father。由于OneToOne關(guān)系中配置casacade=CascadeType.ALL屬性,關(guān)聯(lián)的mySon會(huì)自動(dòng)地被持久化 manager.persist( father ); manager.getTransaction().commit(); manager.close(); 建議在應(yīng)用中盡可能使用cascade=CascadeType.ALL來(lái)減少持久化操作的復(fù)雜性和代碼量,特別是在有復(fù)雜對(duì)象關(guān)系圖的時(shí)候。 4.4獲取Entity如果知道Entity的唯一標(biāo)示符,我們可以用find()方法來(lái)獲得Entity。 Father father = manager.find( Father.class, new Integer( 1 ) ); /由于JDK1.5支持自動(dòng)轉(zhuǎn)型,也可以如下使用 Father father = manager.find( Father.class, 1 ); /* *或者,可以用Entity名字作為查找。但無(wú)法利用JDK 1.5的自動(dòng)轉(zhuǎn)型功能, * 需要使用對(duì)象作為查找主鍵,并需要對(duì)獲得Entity進(jìn)行轉(zhuǎn)型 */ Father father = (Father)manager.find( com.redsoft.samples.Father, new Integer( 1 ) ); 4.5更新Entity對(duì)Entity的更新必須在事物內(nèi)完成。和persist中一樣,關(guān)系元數(shù)據(jù)的cascade屬性對(duì)是否集聯(lián)刪除有影響。 transaction.begin(); Father father = manager.find( Father.class, 1 ); /更新原始數(shù)據(jù)類(lèi)型 father.setName( newName ); /更新對(duì)象引用 Son newSon = new Son(); father.setSon( newSon ); /提交事務(wù),剛才的更新同步到數(shù)據(jù)庫(kù) mit(); 4.6刪除Entity對(duì)Entity的刪除必須在事物內(nèi)完成。 transaction.begin(); Father father = manager.find( Father.class, 1 ); /如果father/son的OneToOne的cascade=CascadeType.ALL,在刪除father時(shí)候,也會(huì)把son刪除。 /把cascade屬性設(shè)為cascade=CascadeType.REMOVE有同樣的效果。 manager.remove( father ); /提交事務(wù),剛才的更新同步到數(shù)據(jù)庫(kù) mit(); 4.7脫離/附合(Detach/Merge)在三層或者分布式應(yīng)用中,我們很多時(shí)候需要Entity能脫離EntityManager,避免長(zhǎng)時(shí)間保持EntityManager打開(kāi)占用資源和可以在不同的JVM之間傳遞Entity。在脫離EJB3 Persistence Runtime(EntityManager)的管理后,我們?nèi)匀豢梢宰x取或者修改Entity中的內(nèi)容。而在稍后的時(shí)間,我們又可以將Entity重新和原有或者新的EntityManager附合,如果附合前Entity被改動(dòng)過(guò),更改的數(shù)據(jù)可以自動(dòng)的被發(fā)現(xiàn)并和數(shù)據(jù)庫(kù)同步。 EntityManager entityManager = emf.createEntityManager(); /這時(shí)Father還是被EntityManager管理的 Father father = manager.find( Father.class, 1 ); /當(dāng)entityManger關(guān)閉的時(shí)候,當(dāng)前被entityManager管理的Entity都會(huì)自動(dòng)的脫離EntityManager,狀態(tài)轉(zhuǎn)變?yōu)閐etached entityManager.close(); /脫離EntityManager后,我們?nèi)匀豢梢孕薷腇ather的屬性 father.setName( newName ); /在稍后的,我們可以將father重新附和到一個(gè)新的或者原來(lái)的EntityManager中 EntityManager newEntityManager = emf.createEntityManager(); /附合( merge )需要在事務(wù)中進(jìn)行 newEntityManager.getTransaction().begin(); newEntityManager.merge( father ); / commit后father中的被修改的內(nèi)容會(huì)同步到數(shù)據(jù)庫(kù)。 newEntityManager.getTransaction().commit(); 5. JPA QueryJPA的查詢(xún)語(yǔ)言(JP)是一種和SQL非常類(lèi)似的中間性和對(duì)象化查詢(xún)語(yǔ)言。它可以被編譯成不同的底層數(shù)據(jù)庫(kù)能接受的SQL,從而屏蔽不同數(shù)據(jù)庫(kù)的差異,確保用JPQL查詢(xún)語(yǔ)言編寫(xiě)的代碼可在不同的數(shù)據(jù)庫(kù)上運(yùn)行。比起EJB 2.1的查詢(xún)語(yǔ)言,EJB3可以運(yùn)行期構(gòu)造,支持多態(tài),遠(yuǎn)遠(yuǎn)比EJB 2.1的查詢(xún)更靈活和功能強(qiáng)大。在程序中使用JPQL可以使用大寫(xiě)(SELECT)或者小寫(xiě)(select),但不要大小寫(xiě)(比如:Select)混合使用。 5.1 Query接口javax.persistence.Query是EJB3查詢(xún)操作的接口。進(jìn)行查詢(xún),首先要通過(guò)EntityManager獲得Query對(duì)象。 public Query createQuery(String ejbqlString); 下面我們做一個(gè)最簡(jiǎn)單的查詢(xún),查詢(xún)所有的com.redsoft.samples.Order類(lèi)。 final Query query = entityManager.createQuery( select o from Order o); final List result = query.getResultList(); final Iterator iterator = result.iterator(); while( iterator.hasNext() ) /處理Order 注意from Order。Order在EJB3查詢(xún)中稱(chēng)為com.redsoft.samples.Order類(lèi)的abstract schema Type。查詢(xún)Entity在JPQL中都是針對(duì)Entity的Abstract Schema Type進(jìn)行查詢(xún)。 在同一個(gè)EntityManagerFactory中,不允許同時(shí)有兩個(gè)Abstract Schema Type相同的Entity類(lèi)。比如不允許同時(shí)有com.redsoft.samples.Order和com.redsoft.foo.Order。 Query返回一個(gè)List的集合結(jié)果,我們可以用Iterator或者List.get( int )的方法來(lái)獲得每個(gè)符合條件的Entity。 如果查詢(xún)結(jié)果結(jié)合中包含所有符合條件的Entity, EJB3 Persistence運(yùn)行環(huán)境默認(rèn)會(huì)自動(dòng)緩存每次查詢(xún)的結(jié)果。這樣下次同樣的查詢(xún)操作就無(wú)需訪問(wèn)數(shù)據(jù)庫(kù),而直接從緩存中返回結(jié)果集合。但如果在下次查詢(xún)操作之前,有針對(duì)被緩存的Entity類(lèi)進(jìn)行update/insert/delete操作,則緩存的結(jié)果集合會(huì)自動(dòng)被清空,這樣下次查詢(xún)就會(huì)從數(shù)據(jù)庫(kù)獲得數(shù)據(jù), 確保查詢(xún)總是獲得正確的結(jié)果,避免緩存臟數(shù)據(jù)。有時(shí)候查詢(xún)會(huì)返回海量的數(shù)據(jù)。注意關(guān)閉對(duì)集合結(jié)果的緩存。 /假設(shè)返回的結(jié)果數(shù)量巨大 final Query query = entityManager.createQuery( select o from Order o); /關(guān)閉對(duì)查詢(xún)結(jié)果的緩存 query.setHint( Constants.QUERY_RESULT_CACHE, false); final List result = query.getResultList(); final Iterator iterator = result.iterator(); /這里我們可以處理海量的數(shù)據(jù) while( iterator.hasNext() ) /處理Order 5.2簡(jiǎn)單查詢(xún)下面是一個(gè)簡(jiǎn)單查詢(xún)的例子,可以看到和SQL的使用方法很類(lèi)似。 final Query query = entityManager.createQuery( select o from Order o where o.id = 1); final Query query = entityManager.createQuery( select o from Order o where o.id = 1 and o.confirm = true ); final Query query = entityManager.createQuery( select o from Order o where o.id = 1 or o.customer = foo ); / address是Order類(lèi)上的一個(gè)對(duì)象變量屬性,Address有一個(gè)streetNumber的屬性final Query query = entityManager.createQuery( select o from Order o where o.address.streetNumber = 123 ); 注意條件語(yǔ)句中查詢(xún)的是Entity的屬性,屬性的名字需要和Entity中的屬性變量名字一致。 5.3使用參數(shù)查詢(xún)參數(shù)查詢(xún)也和SQL中的參數(shù)查詢(xún)類(lèi)似。JPQL支持兩種方式的參數(shù)定義方式:命名參數(shù)和位置參數(shù)。在同一個(gè)查詢(xún)中只允許使用一種參數(shù)定義方式。 final Query query = entityManager.createQuery( select o from Order o where o.id = :myId); /設(shè)置查詢(xún)中的參數(shù) query.setParameter( myId, 2 ); /可以使用多個(gè)參數(shù) final Query query = entityManager.createQuery( select o from Order o where o.id = :myId and o.customer = :customerName ); /設(shè)置查詢(xún)中的參數(shù) query.setParameter( myId, 2 ); query.setParameter( customerName, foo ); final Query query = entityManager.createQuery( select o from Order o where o.id = ?1); /設(shè)置查詢(xún)中的參數(shù) query.setParameter( 1, 2 );/ 1表示第一個(gè)參數(shù),2是參數(shù)的值 /或者 final Query query = entityManager.createQuery( select o from Order o where o.id = ?1).setParameter( 1, 2 ); /可以使用多個(gè)參數(shù) final Query query = entityManager.createQuery( select o from Order o where o.id = ?1 and o.customer = ?2 ); /設(shè)置查詢(xún)中的參數(shù) query.setParameter( 1, 2 ); query.setParameter( 2, foo ); 如果在未來(lái)需要在不同的EJB3運(yùn)行環(huán)境中運(yùn)行,請(qǐng)使用位置參數(shù),保證應(yīng)用是可移植的。 5.4排序(order by)下面是一個(gè)簡(jiǎn)單查詢(xún)的例子,可以看到和SQL的使用方法很類(lèi)似。ASC和DESC分別為升序和降序,如果不顯式注明,JPQL中默認(rèn)為asc升序。 /不注明的話,默認(rèn)為asc為升序, final Query query = entityManager.createQuery( select o from Order o order by o.id); final Query query = entityManager.createQuery( select o from Order o order by o.address.streetNumber desc);/ desc為降序 final Query query = entityManager.createQuery( select o from Order o order by o.id
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- T/CAEPI 70-2023水泥窯協(xié)同處置生活垃圾焚燒飛灰水洗除鹽工藝技術(shù)要求
- 辦理資質(zhì)委托代理協(xié)議3篇
- 食品廠入職合同3篇
- 專(zhuān)業(yè)基礎(chǔ)知識(shí)試題及答案
- 上海數(shù)學(xué)期末試題及答案
- 上戲往試題及答案
- 殘疾人輔助就業(yè) 用工協(xié)議6篇
- 認(rèn)識(shí)媒體和信息素養(yǎng)
- T/ZQIE 006-2023金利五金高品質(zhì)家居用緩沖型杯狀暗鉸鏈
- 問(wèn)卷設(shè)計(jì)說(shuō)明書(shū)
- 2024年中國(guó)航空工裝行業(yè)發(fā)展現(xiàn)狀、市場(chǎng)運(yùn)行態(tài)勢(shì)及發(fā)展前景預(yù)測(cè)報(bào)告
- 中考英語(yǔ)688高頻詞大綱詞頻表
- 一年級(jí)下冊(cè)口算題卡大全(口算練習(xí)題50套直接打印版)
- 外貿(mào)鎖檢測(cè)報(bào)告樣式EN12209
- 無(wú)損檢測(cè)人員登記表
- DB33-T 2048-2017(2021)民宿基本要求與評(píng)價(jià)
- 1員工培訓(xùn)記錄表表格類(lèi)
- 某大學(xué)論文答辯模板課件
- 50以?xún)?nèi)加減法練習(xí)題打印版(100題)
- 基礎(chǔ)體溫表格基礎(chǔ)體溫表
- 煤炭項(xiàng)目建議書(shū)【范文參考】
評(píng)論
0/150
提交評(píng)論