paulwong

          JPA概要

          1 JPA概述

          JPA(Java Persistence API,Java持久化API),定義了對象-關(guān)系映射(ORM)以及實(shí)體對象持久化的標(biāo)準(zhǔn)接口。

          JPA是JSR-220(EJB3.0)規(guī)范的一部分,在JSR-220中規(guī)定實(shí)體對象(EntityBean)由JPA進(jìn)行支持。

          所以JPA不局限于EJB3.0,而是作為POJO持久化的標(biāo)準(zhǔn)規(guī)范,可以脫離容器獨(dú)立運(yùn)行,開發(fā)和測試更加方便。

          JPA在應(yīng)用中的位置如下圖所示:

           

          JPA維護(hù)一個(gè)Persistence Context(持久化上下文),在持久化上下文中維護(hù)實(shí)體的生命周期。主要包含三個(gè)方面的內(nèi)容:

          1. ORM元數(shù)據(jù)。JPA支持annotion或xml兩種形式描述對象-關(guān)系映射。
          2. 實(shí)體操作API。實(shí)現(xiàn)對實(shí)體對象的CRUD操作。
          3. 查詢語言。約定了面向?qū)ο蟮牟樵冋Z言JPQL(Java Persistence Query Language)。

          JPA的主要API都定義在javax.persistence包中。如果你熟悉Hibernate,可以很容易做出對應(yīng):

           
          org.hibernatejavax.persistence說明
          cfg.ConfigurationPersistence讀取配置信息
          SessionFactoryEntityManagerFactory用于創(chuàng)建會(huì)話/實(shí)體管理器的工廠類
          SessionEntityManager提供實(shí)體操作API,管理事務(wù),創(chuàng)建查詢
          TransactionEntityTransaction管理事務(wù)
          QueryQuery執(zhí)行查詢

          2 實(shí)體生命周期

          實(shí)體生命周期是JPA中非常重要的概念,描述了實(shí)體對象從創(chuàng)建到受控、從刪除到游離的狀態(tài)變換。對實(shí)體的操作主要就是改變實(shí)體的狀態(tài)。

          JPA中實(shí)體的生命周期如下圖:

          1. New,新創(chuàng)建的實(shí)體對象,沒有主鍵(identity)值
          2. Managed,對象處于Persistence Context(持久化上下文)中,被EntityManager管理
          3. Detached,對象已經(jīng)游離到Persistence Context之外,進(jìn)入Application Domain
          4. Removed, 實(shí)體對象被刪除

          EntityManager提供一系列的方法管理實(shí)體對象的生命周期,包括:

          1. persist, 將新創(chuàng)建的或已刪除的實(shí)體轉(zhuǎn)變?yōu)镸anaged狀態(tài),數(shù)據(jù)存入數(shù)據(jù)庫。
          2. remove,刪除受控實(shí)體
          3. merge,將游離實(shí)體轉(zhuǎn)變?yōu)镸anaged狀態(tài),數(shù)據(jù)存入數(shù)據(jù)庫。

          如果使用了事務(wù)管理,則事務(wù)的commit/rollback也會(huì)改變實(shí)體的狀態(tài)。

          3 實(shí)體關(guān)系映射(ORM)

          3.1 基本映射

           
          對象端數(shù)據(jù)庫端annotion可選annotion
          ClassTable@Entity@Table(name="tablename")
          propertycolumn@Column(name = "columnname")
          propertyprimary key@Id@GeneratedValue 詳見ID生成策略
          propertyNONE@Transient 

          3.2 ID生成策略

          ID對應(yīng)數(shù)據(jù)庫表的主鍵,是保證唯一性的重要屬性。JPA提供了以下幾種ID生成策略

          1. GeneratorType.AUTO ,由JPA自動(dòng)生成
          2. GenerationType.IDENTITY,使用數(shù)據(jù)庫的自增長字段,需要數(shù)據(jù)庫的支持(如SQL Server、MySQL、DB2、Derby等)
          3. GenerationType.SEQUENCE,使用數(shù)據(jù)庫的序列號(hào),需要數(shù)據(jù)庫的支持(如Oracle)
          4. GenerationType.TABLE,使用指定的數(shù)據(jù)庫表記錄ID的增長 需要定義一個(gè)TableGenerator,在@GeneratedValue中引用。例如:

            @TableGenerator( name="myGenerator", table="GENERATORTABLE", pkColumnName = "ENTITYNAME", pkColumnValue="MyEntity", valueColumnName = "PKVALUE", allocationSize=1 )

            @GeneratedValue(strategy = GenerationType.TABLE,generator="myGenerator")

          3.3 關(guān)聯(lián)關(guān)系

          JPA定義了one-to-one、one-to-many、many-to-one、many-to-many 4種關(guān)系。

          對于數(shù)據(jù)庫來說,通常在一個(gè)表中記錄對另一個(gè)表的外鍵關(guān)聯(lián);對應(yīng)到實(shí)體對象,持有關(guān)聯(lián)數(shù)據(jù)的一方稱為owning-side,另一方稱為inverse-side。

          為了編程的方便,我們經(jīng)常會(huì)希望在inverse-side也能引用到owning-side的對象,此時(shí)就構(gòu)建了雙向關(guān)聯(lián)關(guān)系。 在雙向關(guān)聯(lián)中,需要在inverse-side定義mappedBy屬性,以指明在owning-side是哪一個(gè)屬性持有的關(guān)聯(lián)數(shù)據(jù)。

          對關(guān)聯(lián)關(guān)系映射的要點(diǎn)如下:

           
          關(guān)系類型Owning-SideInverse-Side
          one-to-one@OneToOne@OneToOne(mappedBy="othersideName")
          one-to-many / many-to-one@ManyToOne@OneToMany(mappedBy="xxx")
          many-to-many@ManyToMany@ManyToMany(mappedBy ="xxx")

          其中 many-to-many關(guān)系的owning-side可以使用@JoinTable聲明自定義關(guān)聯(lián)表,比如Book和Author之間的關(guān)聯(lián)表:

          @JoinTable(name = "BOOKAUTHOR", joinColumns = { @JoinColumn(name = "BOOKID", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "AUTHORID", referencedColumnName = "id") })

          關(guān)聯(lián)關(guān)系還可以定制延遲加載和級聯(lián)操作的行為(owning-side和inverse-side可以分別設(shè)置):

          通過設(shè)置fetch=FetchType.LAZY 或 fetch=FetchType.EAGER來決定關(guān)聯(lián)對象是延遲加載或立即加載。

          通過設(shè)置cascade={options}可以設(shè)置級聯(lián)操作的行為,其中options可以是以下組合:

          • CascadeType.MERGE 級聯(lián)更新
          • CascadeType.PERSIST 級聯(lián)保存
          • CascadeType.REFRESH 級聯(lián)刷新
          • CascadeType.REMOVE 級聯(lián)刪除
          • CascadeType.ALL 級聯(lián)上述4種操作

          3.4 繼承關(guān)系

          JPA通過在父類增加@Inheritance(strategy=InheritanceType.xxx)來聲明繼承關(guān)系。A支持3種繼承策略:

          1. 單表繼承(InheritanceType.SINGLETABLE),所有繼承樹上的類共用一張表,在父類指定(@DiscriminatorColumn)聲明并在每個(gè)類指定@DiscriminatorValue來區(qū)分類型。
          2. 類表繼承(InheritanceType.JOINED),父子類共同的部分公用一張表,其余部分保存到各自的表,通過join進(jìn)行關(guān)聯(lián)。
          3. 具體表繼承(InheritanceType.TABLEPERCLASS),每個(gè)具體類映射到自己的表。

          其中1和2能夠支持多態(tài),但是1需要允許字段為NULL,2需要多個(gè)JOIN關(guān)系;3最適合關(guān)系數(shù)據(jù)庫,對多態(tài)支持不好。具體應(yīng)用時(shí)根據(jù)需要取舍。

          4 事件及監(jiān)聽

          通過在實(shí)體的方法上標(biāo)注@PrePersist,@PostPersist等聲明即可在事件發(fā)生時(shí)觸發(fā)這些方法。

          5 Query Language 查詢語言

          JPA提供兩種查詢方式,一種是根據(jù)主鍵查詢,使用EntityManager的find方法:

          T find(Class entityClass, Object primaryKey)

          另一種就是使用JPQL查詢語言。JPQL是完全面向?qū)ο蟮模邆淅^承、多態(tài)和關(guān)聯(lián)等特性,和hibernate HQL很相似。

          使用EntityManager的createQuery方法:

          Query createQuery(String qlString)

          5.1 使用參數(shù)

          可以在JPQL語句中使用參數(shù)。JPQL支持命名參數(shù)和位置參數(shù)兩種參數(shù),但是在一條JPQL語句中所有的參數(shù)只能使用同一種類型。

          舉例如下:

          • 命令參數(shù)

          Query query = em.createQuery("select p from Person p where p.personid=:Id"); query.setParameter("Id",new Integer(1));

          • 位置參數(shù)

          Query query = em.createQuery("select p from Person p where p.personid=?1"); query.setParameter(1,new Integer(1));

          5.2 命名查詢

          如果某個(gè)JPQL語句需要在多個(gè)地方使用,還可以使用@NamedQuery 或者 @NamedQueries在實(shí)體對象上預(yù)定義命名查詢。

          在需要調(diào)用的地方只要引用該查詢的名字即可。

          例如:

          @NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1")

          @NamedQueries({ @NamedQuery(name="getPerson1", query= "FROM Person WHERE personid=?1"), @NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1") })

          Query query = em.createNamedQuery("getPerson");

          5.3 排序

          JPQL也支持排序,類似于SQL中的語法。例如: Query query = em.createQuery("select p from Person p order by p.age, p.birthday desc");

          5.4 聚合查詢

          JPQL支持AVG、SUM、COUNT、MAX、MIN五個(gè)聚合函數(shù)。例如:

          Query query = em.createQuery("select max(p.age) from Person p"); Object result = query.getSingleResult(); String maxAge = result.toString();

          5.5 更新和刪除

          JPQL不僅用于查詢,還可以用于批量更新和刪除。

          如:

          Query query = em.createQuery("update Order as o set o.amount=o.amount+10"); //update 的記錄數(shù) int result = query.executeUpdate();

          Query query = em.createQuery("delete from OrderItem item where item.order in(from Order as o where o.amount<100)"); query.executeUpdate();

          query = em.createQuery("delete from Order as o where o.amount<100"); query.executeUpdate();//delete的記錄數(shù)

          5.6 更多

          與SQL類似,JPQL還涉及到更多的語法,可以參考:http://docs.oracle.com/cd/E11035_01/kodo41/full/html/ejb3_langref.html

          6 事務(wù)管理

          JPA支持本地事務(wù)管理(RESOURCELOCAL)和容器事務(wù)管理(JTA),容器事務(wù)管理只能用在EJB/Web容器環(huán)境中。

          事務(wù)管理的類型可以在persistence.xml文件中的“transaction-type”元素配置。

          JPA中通過EntityManager的getTransaction()方法獲取事務(wù)的實(shí)例(EntityTransaction),之后可以調(diào)用事務(wù)的begin()、commit()、rollback()方法。

          Date: 2012-12-30 16:46:29 CST

          Author: Holbrook

          Org version 7.8.11 with Emacs version 24

          posted on 2016-06-04 16:08 paulwong 閱讀(566) 評論(0)  編輯  收藏 所屬分類: HIBERNATE

          主站蜘蛛池模板: 泗水县| 开鲁县| 环江| 安岳县| 铜鼓县| 吉安县| 句容市| 康平县| 大荔县| 枝江市| 特克斯县| 金川县| 莲花县| 凉山| 徐闻县| 福鼎市| 安新县| 琼海市| 庆元县| 德江县| 金坛市| 郓城县| 宾川县| 乌鲁木齐县| 砀山县| 罗田县| 荆州市| 长沙市| 咸宁市| 高密市| 夏津县| 大丰市| 铜陵市| 苗栗市| 夹江县| 江西省| 天祝| 祁阳县| 环江| 溧水县| 马公市|