JPA

1 JPA概述

JPA(Java Persistence API,Java持久化API),定義了對象-關係映射(ORM)以及實體對象持久化的標準接口。html

JPA是JSR-220(EJB3.0)規範的一部分,在JSR-220中規定實體對象(EntityBean)由JPA進行支持。java

因此JPA不侷限於EJB3.0,而是做爲POJO持久化的標準規範,能夠脫離容器獨立運行,開發和測試更加方便。數據庫

JPA在應用中的位置以下圖所示:編程

 

JPA維護一個Persistence Context(持久化上下文),在持久化上下文中維護實體的生命週期。主要包含三個方面的內容:oracle

  1. ORM元數據。JPA支持annotion或xml兩種形式描述對象-關係映射。
  2. 實體操做API。實現對實體對象的CRUD操做。
  3. 查詢語言。約定了面向對象的查詢語言JPQL(Java Persistence Query Language)。

JPA的主要API都定義在javax.persistence包中。若是你熟悉Hibernate,能夠很容易作出對應:app

 
org.hibernate javax.persistence 說明
cfg.Configuration Persistence 讀取配置信息
SessionFactory EntityManagerFactory 用於建立會話/實體管理器的工廠類
Session EntityManager 提供實體操做API,管理事務,建立查詢
Transaction EntityTransaction 管理事務
Query Query 執行查詢

2 實體生命週期

實體生命週期是JPA中很是重要的概念,描述了實體對象從建立到受控、從刪除到遊離的狀態變換。對實體的操做主要就是改變實體的狀態。ide

JPA中實體的生命週期以下圖:函數

  1. New,新建立的實體對象,沒有主鍵(identity)值
  2. Managed,對象處於Persistence Context(持久化上下文)中,被EntityManager管理
  3. Detached,對象已經遊離到Persistence Context以外,進入Application Domain
  4. Removed, 實體對象被刪除

EntityManager提供一系列的方法管理實體對象的生命週期,包括:post

  1. persist, 將新建立的或已刪除的實體轉變爲Managed狀態,數據存入數據庫。
  2. remove,刪除受控實體
  3. merge,將遊離實體轉變爲Managed狀態,數據存入數據庫。

若是使用了事務管理,則事務的commit/rollback也會改變實體的狀態。測試

3 實體關係映射(ORM)

3.1 基本映射

 
對象端 數據庫端 annotion 可選annotion
Class Table @Entity @Table(name="tablename")
property column @Column(name = "columnname")
property primary key @Id @GeneratedValue 詳見ID生成策略
property NONE @Transient  

3.2 ID生成策略

ID對應數據庫表的主鍵,是保證惟一性的重要屬性。JPA提供瞭如下幾種ID生成策略

  1. GeneratorType.AUTO ,由JPA自動生成
  2. GenerationType.IDENTITY,使用數據庫的自增加字段,須要數據庫的支持(如SQL Server、MySQL、DB二、Derby等)
  3. GenerationType.SEQUENCE,使用數據庫的序列號,須要數據庫的支持(如Oracle)
  4. GenerationType.TABLE,使用指定的數據庫表記錄ID的增加 須要定義一個TableGenerator,在@GeneratedValue中引用。例如:

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

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

3.3 關聯關係

JPA定義了one-to-one、one-to-many、many-to-one、many-to-many 4種關係。

對於數據庫來講,一般在一個表中記錄對另外一個表的外鍵關聯;對應到實體對象,持有關聯數據的一方稱爲owning-side,另外一方稱爲inverse-side。

爲了編程的方便,咱們常常會但願在inverse-side也能引用到owning-side的對象,此時就構建了雙向關聯關係。 在雙向關聯中,須要在inverse-side定義mappedBy屬性,以指明在owning-side是哪個屬性持有的關聯數據。

對關聯關係映射的要點以下:

 
關係類型 Owning-Side Inverse-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關係的owning-side可使用@JoinTable聲明自定義關聯表,好比Book和Author之間的關聯表:

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

關聯關係還能夠定製延遲加載和級聯操做的行爲(owning-side和inverse-side能夠分別設置):

經過設置fetch=FetchType.LAZY 或 fetch=FetchType.EAGER來決定關聯對象是延遲加載或當即加載。

經過設置cascade={options}能夠設置級聯操做的行爲,其中options能夠是如下組合:

  • CascadeType.MERGE 級聯更新
  • CascadeType.PERSIST 級聯保存
  • CascadeType.REFRESH 級聯刷新
  • CascadeType.REMOVE 級聯刪除
  • CascadeType.ALL 級聯上述4種操做

3.4 繼承關係

JPA經過在父類增長@Inheritance(strategy=InheritanceType.xxx)來聲明繼承關係。A支持3種繼承策略:

  1. 單表繼承(InheritanceType.SINGLETABLE),全部繼承樹上的類共用一張表,在父類指定(@DiscriminatorColumn)聲明並在每一個類指定@DiscriminatorValue來區分類型。
  2. 類表繼承(InheritanceType.JOINED),父子類共同的部分公用一張表,其他部分保存到各自的表,經過join進行關聯。
  3. 具體表繼承(InheritanceType.TABLEPERCLASS),每一個具體類映射到本身的表。

其中1和2可以支持多態,可是1須要容許字段爲NULL,2須要多個JOIN關係;3最適合關係數據庫,對多態支持很差。具體應用時根據須要取捨。

4 事件及監聽

經過在實體的方法上標註@PrePersist,@PostPersist等聲明便可在事件發生時觸發這些方法。

5 Query Language 查詢語言

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

T find(Class entityClass, Object primaryKey)

另外一種就是使用JPQL查詢語言。JPQL是徹底面向對象的,具有繼承、多態和關聯等特性,和hibernate HQL很類似。

使用EntityManager的createQuery方法:

Query createQuery(String qlString)

5.1 使用參數

能夠在JPQL語句中使用參數。JPQL支持命名參數和位置參數兩種參數,可是在一條JPQL語句中全部的參數只能使用同一種類型。

舉例以下:

  • 命令參數

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

  • 位置參數

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

5.2 命名查詢

若是某個JPQL語句須要在多個地方使用,還可使用@NamedQuery 或者 @NamedQueries在實體對象上預約義命名查詢。

在須要調用的地方只要引用該查詢的名字便可。

例如:

@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五個聚合函數。例如:

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 的記錄數 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的記錄數

5.6 更多

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

6 事務管理

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

事務管理的類型能夠在persistence.xml文件中的「transaction-type」元素配置。

JPA中經過EntityManager的getTransaction()方法獲取事務的實例(EntityTransaction),以後能夠調用事務的begin()、commit()、rollback()方法。

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

Author: Holbrook

Org version 7.8.11 with Emacs version 24

Validate XHTML 1.0
相關文章
相關標籤/搜索