四階段錄屏jpa基礎_第1頁
四階段錄屏jpa基礎_第2頁
四階段錄屏jpa基礎_第3頁
四階段錄屏jpa基礎_第4頁
四階段錄屏jpa基礎_第5頁
已閱讀5頁,還剩39頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

JPA概述2

什么是JPAJPA(JavaPersistenceAPI)是Sun官方提出的Java持久化規范。它為Java開發人員提供了一種對象/關系映射工具來管理Java應用中的關系數據。他的出現主要是為了簡化現有的持久化開發工作和整合ORM技術,結束現在Hibernate、TopLink等ORM框架各自為營的局面。值得注意的是,JPA是在充分吸收了現有Hibernate、TopLink等ORM框架的基礎上發展而來的,具有易于使用、伸縮性強等優點。從目前的開發社區的反應上看,JPA受到了極大的支持和贊揚,其中就包括了Spring與EJB3.0的開發團隊。著眼未來幾年的技術走向,JPA作為ORM領域標準化整合者的目標應該不難實現。3

什么是JPAJPA的總體思想和現有Hibernate、TopLink等ORM框架大體一致。總的來說,JPA包括以下3方面的技術:ORM映射元數據JPA支持XML和JDK5.0注釋(也可譯作注解)兩種元數據的形式,元數據描述對象和表之間的映射關系,框架據此將實體對象持久化到數據庫表中。Java持久化API用來操作實體對象,執行CRUD操作,框架在后臺替我們完成所有的事情,開發者可以從繁瑣的JDBC和SQL代碼中解脫出來。查詢語言(JPQL)這是持久化操作中很重要的一個方面,通過面向對象而非面向數據庫的查詢語言查詢數據,避免程序的SQL語句緊密耦合。提示:JPA不是一種新的ORM框架,他的出現只是用于規范現有的ORM技術,他不能取代現有的Hibernate、TopLink等ORM框架。相反,在采用JPA開發時,我們仍將使用到這些ORM框架,只是此時開發出來的應用不再依賴于某個持久化提供商。應用可以在不修改代碼的情況下在任何JPA環境下運行,真正做到低耦合,可擴展的程序設計。4開發JPA依賴的jar文件Hiberante核心包(8個文件)hibernate-distribution-3.3.1.GA---------------------------------------------hibernate3.jarlib\bytecode\cglib\hibernate-cglib-repack-2.1_3.jarlib\required\*.jarHiberante注解包(3個文件):hibernate-annotations-3.4.0.GA------------------------------------------------------------------------------------hibernate-annotations.jarlib\ejb3-persistence.jar、mons-annotations.jarHibernate針對JPA的實現包(3個文件):hibernate-entitymanager-3.4.0.GA------------------------------------------------------------------------------------------------------hibernate-entitymanager.jarlib\test\log4j.jar、slf4j-log4j12.jar5JPA的配置文件JPA規范要求在類路徑的META-INF目錄下放置persistence.xml,文件的名稱是固定的,配置模版如下:<?xmlversion="1.0"?><persistencexmlns=""xmlns:xsi=""xsi:schemaLocation="/persistence_1_0.xsd"version="1.0"><persistence-unitname="itcast"transaction-type="RESOURCE_LOCAL"><properties><propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQL5Dialect"/><propertyname="hibernate.connection.driver_class"value="org.gjt.mm.mysql.Driver"/><propertyname="hibernate.connection.username"value="root"/><propertyname="hibernate.connection.password"value="123456"/><propertyname="hibernate.connection.url"value="jdbc:mysql://localhost:3306/itcast?useUnicode=true&characterEncoding=UTF-8"/><propertyname="hibernate.hbm2ddl.auto"value="update"/></properties></persistence-unit></persistence>6什么是JPA?JPA的生命周期分離狀態自由狀態持久狀態刪除狀態7持久化實體管理器EntityManagerEntityManager

在JavaPersistence(持久)規范中,EntityManager是為持久化操作提供服務的中樞。實體作為普通java對象,只有在調用EntityManager將其持久化后才會變成持久對象。EntityManager對象在一組固定的實體類與底層數據源之間進行O/R映射的管理。它可以用來管理和更新EntityBean,根椐主鍵查找EntityBean,還可以通過JPQL語句查詢實體。當EntityManager注入到EJB容器中,EJB容器會對EntityManager對象所依賴的持久上下文環境具有完全的控制權。

實體的狀態:新建狀態:新創建的對象,尚未擁有持久性主鍵。托管狀態:已經擁有持久性主鍵并和持久化建立了上下文環境游離狀態:擁有持久化主鍵,但是沒有與持久化建立上下文環境刪除狀態:擁有持久化主鍵,已經和持久化建立上下文環境,但是從數據庫 中刪除。8持久化實體管理器EntityManagerEntityManager常用方法persist(Object)–使實體類從new狀態或者removed轉變到managed狀態,并將數據保存到底層數據庫中,相當于save()方法remove(Object)–將實體變為removed狀態,當實體管理器關閉或者刷新時,會真正的刪除數據find(ClassentityClass,Objectkey)–以主鍵查詢實體對象,entityClass是實體的類,key是主鍵值。相當于原先Hibernate的Load與Get方法。flush()–將實體和底層的數據庫進行同步,當我們調用persist(),merge()remove()這些方法時,更新并不會立刻同步到數據庫中,直到容器決定刷新到數據庫中時才會執行,我們可以調用flush()強制更新createQuery() –根據JPAQL定義查詢對象createNativeQuery()–允許開發人員根據特定數據庫的SQL語法來進行查詢操作,只 有JPAQL不能滿足要求時才使用它merge(Object) –將一個detached的實體持久化到數據庫中,并轉換為managed狀態,相當于update()方法close() –關閉實體管理器,并且會嘗試更新所有數據9持久化實體管理器EntityManagerEntity獲得find()或getReference()

如果知道Entity的主鍵,可以通過find()或getReference()方法獲得。方法的第一個參數為實體類(class類型),第二個參數為Entity的OID(OID為類標識符,也就是@ID指定的屬性值)find()方法返回指定的OID實體,如果這個實體存在于當前的持久化環境,則返回一個被緩存的對象,否則會創建一個新的Entity,并加載數據庫中相關信息,同時OID不存在于數據庫中,則返回一個null。getReference()方法與find()方法類似,不同的是:如果緩存中不在存指定的Entity,EntityManager會創建一個Entity類的代理,但是不會立即加載數據庫中的信息,只有第一次真正使用此Entity的屬性才加載,所以如果此OID在數據庫不存在,getReference()不會返回null值,而是拋出EntityNotFoundException10演示案例當我們要使用getReference()方法的時候,我們獲取的對象只是一個代理對象,這個時候我們需要在方法中使用一個對象才能實現代理對象轉向實例對象。publicStuInfogetStuInfoRe(Integerid){StuInfosInfo=newStuInfo();try{sInfo=em.getReference(StuInfo.class,id);//此處我們需要使用任何一種方式,但只需要引用sInfo對象即可System.out.println(sInfo);//此處我們可以模擬游離狀態}catch(EntityNotFoundExceptionnotFound){//TODO:handleexception}returnsInfo;}11持久化實體管理器EntityManager持久化實體persist() persist()用于將新創建的Entity納入到EntityManager的管理。該方法執行后,傳入persist()方法的Entity對象轉換成托管狀態。如果傳入persist()方法的Entity對象已經處于托管狀態,則persist()方法什么事情都不做。如果對刪除狀態的Entity進行persist()操作,會轉換為托管狀態。如果對游離狀態的實體執行persist()操作,可能會在persist()方法拋出EntityExistException(也有可能是在flush或事務提交后拋出)。12持久化實體管理器EntityManager合并實體merge() merge()用于處理Entity的同步。即數據庫的插入和更新操作,因為Entity對象有可能被序列化傳遞到客戶端,然后在客戶端修改了相關的屬性后再將Entity對象傳輸到服務器端。在服務端需要將這個游離的實體納入到EntityManager的管理中,從而使數據同步到數據庫中。對于不同狀態的Entity對象調用merge()方法具有以下行為:如果是新建實體,則會創建該Entity的一份拷貝納入到EntiytManager中, 所以此特性也可以用于保存數據如果是托管狀態,merge()操作會被忽略如果是刪除狀態,merge()操作會拋出IllegalumentException如果是游離狀態,則執行規則如下:a.如果此時容器中存在相同主鍵的實體B,則會將傳進來的實體參數copy到對象B,容器會將B對象中的屬性同步到數據庫。

b.如果容器中不存相同的主鍵的實體,容器則會創建該實體的一份copy

對象B,然后將對象B納入到EntityManager管理中。13演示案例增加一修改方法publicvoidupdateStuInfo(StuInfostuInfo){ em.merge(stuInfo);}1、測試方法一:采用對原數據進行修改。測試一下,可以采用修改之前和修改之后的數據進行對比.2、測試方法二:對新數據進行添加保存StuInfostuInfo=newStuInfo();stuInfo.setStuname("zhangsan");stuInfo.setStuaddress("株洲");stm.updateStuInfo(stuInfo);14持久化實體管理器EntityManager刪除remove()

需要刪除某個實體對象,也就是刪除數據庫中某條記錄。當remove()方法是在事務外調用,則會拋出TransactionRequriedException。對于處于不同狀態的實體,執行remove()方法具有以下行為:如果是新建狀態,則此操作會被忽略如果是托管狀態,則此實體會被刪除如果是刪除狀態,則此操作會被忽略如果是游離狀態,那么會導致IllegalArgumentException。15演示案例定義一個刪除方法:publicvoidremoveStuInfo(Integerid){StuInfosInfo=this.getStuInfo(id);em.remove(sInfo);}這個時候,我們可以模擬游離狀態。改寫修改方法publicvoidremoveStuInfo(StuInfosInfo){em.remove(sInfo);}

//測試代碼這樣寫,我們則會得到IllegalArgumentException異常情況StuInfosInfo=newStuInfo();sInfo=stm.getStuInfoRe(2100);stm.removeStuInfo(sInfo);System.out.println(sInfo.getStuname()+"的地址是:"+sInfo.getStuaddress());16持久化實體管理器EntityManager執行JPQL操作createQuery()ObjectgetSingleResult():執行SELECT查詢語句,并返回一個結果;ListgetResultList():執行SELECT查詢語句,并返回多個結果;QuerysetParameter(intposition,Objectvalue):通過參數位置號綁定查詢語句中的參數,QuerysetParameter(Stringname,Objectvalue)方法綁定命名參數;QuerysetMaxResults(intmaxResult):設置返回的最大結果數;QuerysetFirstResult(intfirstResult):設置返回的結果開始下標。intexecuteUpdate():如果查詢語句是新增、刪除或更改的語句,通過該方法執行更新操作;17持久化實體管理器EntityManager執行SQL操作createNativeQuery()

如果要執行SQL語句,則可以使用createNativeQuery()方法。注意在這里使用的SQL語句,而不是JPQL語句。執行數據庫中的SQL語句18持久化實體管理器EntityManager刷新實體refresh() 如果你懷疑當前托管對象存放的并非數據庫最新數據,(比如:在你執行了find()方法之后,有人悄悄在數據庫中修改了數據),可以通過使用refresh()方法刷新體。

如在實體在不同狀態,調用refresh()方法,會具有以下行為:如果是新建狀態,則此操作那么會導致IllegalArgumentException如果是托管狀態,則此實體會刷新實體對象如果是刪除狀態,則此操作那么會導致IllegalArgumentException如果是游離狀態,那么會導致IllegalArgumentException19利用JPA完成IDUQ的功能完整案例:CRUD的過程.java小結:EntityManager實現操作的過程。20關系與對象映射雙向一對多及多對一映射

當one的一方存在與many一方關系的定義,而many也存在one一方關系的定義時,叫做雙向關系。代碼中體現在one的一方存在一個集合屬性指向many一方,而many一方也存一個屬性指向one的一方。訂單表訂單明細表21關系與對象映射雙向一對多及多對一映射

雙向一對多關系中,必順存在一個關系維護端,在JPA規范中,要求many的一方作為關系的維護端(ownerside),one的一方作為被維護端(inverseside)。我們可以在one方指定@OneToMany注釋并設置mappedBy屬性,以指定它是這一關聯中的被維護端,many為維護端。在one一方維護一對多的關系Public@interfaceOneToMany{CascadeType[] cascade()default{}

FetchType fetch()defaultFetchType.LAZYString mappedBy()default""Class targetEntity()defaultvoid.class}指定要關聯的Entity對象,一般不需要設定指定實體關系中的cascade動作CascadeType.PERSIST

CascadeType.REMOVECascadeType.REFRESHCascadeType.MERGECascadeType.ALL

Fetch用于指定屬性在首次加載實體是采用即時加載或延時加載.fetch的值在FetchType.LAZY:設定為延遲加載(默認值)FetchType.EAGER:設定為即時加載用于指向被關聯實體中的指向自已的屬性成員名稱22關系與對象映射雙向一對多及多對一映射 在many中也需要設置與one的一方進行關聯。Public@interfaceManyToOne{CascadeType[] cascade()default{}FetchTypefetch()defaultFetchType.LAZYbooleanoptional()defaulttrueClass targetEntity()}含義與OneToMany一樣設定關聯方是否允許為null值,當值設為true時,允許外鍵字段為null,當值設為false時,不允許外鍵字段為null用于指向與在One中包含自已的屬性名稱指向多表中的外鍵字段23演示案例Orders//Orders表實體@Entity@Table(name="orders",schema="t27")publicclassOrdersimplementsSerializable{privateIntegerorderid;privateFloatamount;//在單的一方,用一個Set進行概括.privateSetorderSet=newHashSet();….@OneToMany(mappedBy="orders",cascade=CascadeType.ALL,fetch=FetchType.EAGER,targetEntity=OrderItem.class)publicSetgetOrderSet(){returnorderSet;}public

voidsetOrderSet(SetorderSet){this.orderSet=orderSet;}24演示案例OrdersItem@Entity@Table(name="orderitem",schema="t27")publicclassOrderItemimplementsSerializable{privateIntegerid;privateStringproductname;privateFloatprice;//在多的一方,用Order對象進行描述.privateOrdersorders;@ManyToOne(cascade=CascadeType.REFRESH,optional=false,targetEntity=Orders.class)@JoinColumn(name="ORDERID")publicOrdersgetOrders(){returnorders;}publicvoidsetOrders(Ordersorders){this.orders=orders;}25測試代碼2-1//通過單的一方,查找多的一方。publicSetloadOrderItem(Integerid){//TODOAuto-generatedmethodstubOrdersorders=eManager.find(Orders.class,id);if(orders!=null){returnorders.getOrderItem();}returnnull;}//通過多的一方,查找單的一方。publicOrdersloadbymany(Integerid){Ordersorders=newOrders();OrderItemorderItem=eManager.find(OrderItem.class,id);orders=orderItem.getOrders();returnorders;}26測試代碼2-1publicbooleanaddOnOne(Integerorderid,Stringordername1,Stringordername2){try{Ordersorders=newOrders();orders.setOrderid(orderid);orders.setAmount(newFloat(500));OrderItemoItem1=newOrderItem();oItem1.setOrders(orders);oItem1.setProductname(ordername1);oItem1.setPrice(newFloat(1000));oItem1.setId(10);OrderItemoItem2=newOrderItem();oItem2.setOrders(orders);oItem2.setProductname(ordername2);oItem2.setPrice(newFloat(1000));oItem2.setId(11);orders.getOrderSet().add(oItem1);orders.getOrderSet().add(oItem2);eManager.persist(orders);}catch(Exceptione){//TODO:handleexceptionreturnfalse;}returntrue;}在單的一方增加對象的方法。27測試代碼2-2//通過多的一方,查找單的一方InitialContextctx=newInitialContext();OrderManagerstm=(OrderManager)ctx.lookup("OrderManagerBean/remote");Setset=(Set)stm.loadOrderItem(1);Iteratoriterator=set.iterator();while(iterator.hasNext()){OrderItemorders=(OrderItem)iterator.next();System.out.println("定單1下面的產品名稱有:"+orders.getProductname());//通過單的一方,查找多的一方InitialContextctx=newInitialContext();OrderManagerstm=(OrderManager)ctx.lookup("OrderManagerBean/remote");Ordersorders=stm.loadbymany(2);System.out.println("定單明細編號為2的定單編號是"+orders.getOrderid());28多對一關系中--注意11、有關mappingby屬性設置29多對一關系中--注意22、關聯關系應用中,我們盡量將屬性的注釋寫在方法之上。3、在進行Set映射對象描述的時候,一定需要實例化對象

//在單的一方,用一個Set進行概括. privateSetorderSet=newHashSet();30關系與對象映射雙向一對一映射

在二個對象中,互相包含一個對方的屬性,形成了一種雙向一對一的關系。31關系與對象映射雙向一對一映射 在雙向的一對一關聯中,我們需要在關系被維護端(inverseside)中的@OneToOne注釋中指定mappedBy,以指定它是這一關聯中的被維護端。同時需要在關系維護端(ownerside)建立外鍵列指向關系被維護端的主鍵列。指定OneToOne關系指定外鍵字段,指定此實體為ownerside32關系與對象映射雙向一對一關系Public@interfaceOneToOne{CascadeType[] cascade()default{}FetchTypefetch()defaultFetchType,EAGERClass targetEntity()defaultvoid.classStringmappedBy();booleanoptional()defaulttrue}與ManyToOne中屬性一樣Optional的值設為True用于指定允許外鍵字段為nullOptional的值設為false用于指定不允許外鍵字段為null33實現思路3-11、Person實體privateIntegerpersonid;privateStringpersonname;privateIdcardidcard;//取對象的實例@OneToOne(cascade=CascadeType.ALL,optional=true)//name取數據庫中的字段,映射對象為IdCard的主鍵映射對象,唯一特性@JoinColumn(name="idcardid",referencedColumnName="id",unique=true)publicIdcardgetIdcard(){returnidcard;}publicvoidsetIdcard(Idcardidcard){this.idcard=idcard;}@IdpublicIntegergetPersonid(){returnpersonid;}publicvoidsetPersonid(Integerpersonid){this.personid=personid;}@ColumnpublicStringgetPersonname(){returnpersonname;}publicvoidsetPersonname(Stringpersonname){this.personname=personname;}34實現思路3-22、Idcard實體@Entity@Table(name="Idcard",schema="t27")publicclassIdcardimplementsSerializable{privateIntegerid;privateStringcardno;privatePersonperson;//mappedBy指向對象的實例,則由對象管理。@OneToOne(cascade=CascadeType.REFRESH,optional=false,mappedBy="idcard")publicPersongetPerson(){returnperson;}publicvoidsetPerson(Personperson){this.person=person;}@ColumnpublicStringgetCardno(){returncardno;}publicvoidsetCardno(Stringcardno){this.cardno=cardno;}@IdpublicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.id=id;}35實現思路3-33、寫一個遠程無狀態sessionBean進行操作@PersistenceContext(unitName="StuInfo")EntityManagereManager;publicbooleansaveOne(StringperName,StringcardNo){try{Personperson=newPerson();person.setPersonname(perName);person.setPersonid(5);Idcardidcard=newIdcard();idcard.setId(5);idcard.setCardno(cardNo);person.setIdcard(idcard);idcard.setPerson(person);//此處由person管理,不能由card管理eManager.persist(person);//eManager.persist(idcard);}catch(Exceptione){//TODO:handleexceptionreturnfalse;}returntrue;}36關系與對象映射雙向多對多關系

在現實生活中存在很多多對多關系,比如說學生與老師的關系,多對多關系我們通過采用中間表的策略來建立映射策略。37關系與對象映射雙向多對多關系 在雙向多對多關系中,我們必順指定一個關系維護端(ownerside),同樣我們可以通過@ManyToMany注釋中指定mappedBy屬性來標識其為關系維護端。指定對應的多對多關系38關系與對象映射雙向多對多關系Public@interfaceManyToMany{CascadeType[] cascade()default{}FetchTypefetch()defaultFetchType.LAZYClass targetEntity()defaultvoid.classStringmappedBy();}與OneToMany中的屬性一樣@JoinTable用于指定中間表信息39關系與對象映射雙向多對多關系 在雙向多對多關系中,只需要在關系維護端定義此屬性。Public@interfaceJoinTable{Stringcatalog()default“”;Stringschema()default“”;

Stringname()default“”;JoinColumn[]joinColumns()default{};JoinColumn[]inverseJoinColumns()default{};UniqueConstraintsUniquenConstraints()default{};}中間表在數據庫的相關信息指定與關系維護端關聯的字段指定與關系被維護端關聯的字段40實現思路1、Student實體//屬性privateIntegerstuid;privateStringstuname;privateSetteacher=newHashSet();//stu_tea關聯表,joinColumns關聯表字段關系,inverseJoinColumns反轉關系@ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.EAGER,targetEntity=Teacher.class)@JoinTable(name="stu_tea

溫馨提示

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

評論

0/150

提交評論