* Java Persistence API (Java 持久層/永續層 API)
* 通過 註解(Annotation, JDK5.0) 或 XML 描述方式,將 物件-關聯表的映射關係 (O-R Mapping / ORM)和運行期 Entity object 持久化到資料庫中去。
* Object/Relational Mapping (ORM)
- 簡單的說就是將 Java 中的物件與物件關係,映射至關聯式資料庫中的表格與表格之間的關係
- 使用JPA,底層可以使用不同廠商的ORM實作,而介面則是JPA的標準,ex:
- NetBeans + Glassfish,則預設的底層實作為TopLink。
- JBoss的工具其底層實作則為Hibernate
* Persistence in this context covers three areas:
- the API itself, defined in the javax.persistence package
- the Java Persistence Query Language (JPQL)
- object/relational metadata
* 持久性/永續層
- 相對於只能存活於 JRE Heap 中的 object 來說, 需要能將大量的 object 資訊與 state 保存在一個儲存體中, 提供經常性重複存取物件屬性的 data 機制, JPA 即提供了一個 Java 標準的 Persistence 解決方案.
- Persistence 的儲存標的物可以是 file 或是 DB.
[Annotation]
* @Entity: 成為 JPA 的 Entity 類別,或者 XML 映射中有對應的
* @Table: 標示這個Entity類別對應的資料表格,若類別名稱與表格名稱相同,則可以省略,預設會將類別名稱對應至同名的表格,Entity類別必須實作Serializable介面。
* @Id: 使用此標註在資料成員或Getter方法上,使每個Entity類別必須有獨一無二的識別屬性,並與資料表格的主鍵相對應。
* @GeneratedValue: 可以選擇主鍵的產生策略,ex: @GeneratedValue(strategy = GenerationType.AUTO),在這邊利用資料庫本身的自動產生策略,由底層的資料庫來提供。
* @Column: 若成員名稱與表格欄位名稱一樣,則會自動對應,若不同,則可以使用@Column來指定欄位名稱。
[Implement]
- 為了JPA必須設定資料庫連結與底層實作的一些細節,您要在META-INF下撰寫一個 persistence.xml。
- 建立EntityManagerFactory,EntityManagerFactory內含設定資訊,負責管理 EntityManager,而這樣的方式所取得的EntityManager,稱之為 Application-Managed EntityManager。
- 取得EntityManager後,可透過getTransaction()取得 EntityTransaction
- EntityTransaction 負責管理交易,透過EntityManger的persist()方法來儲存User物件,EntityManager會自動將對應的成員儲存至對應的資料表格欄位,
- 若透過EntityManager的find()方法,指定主鍵來查找資料並封裝為User物件,基本上所有的EntityManager操作,要在交易中完成,但find()可以不用在交易中完成,只不過若不在交易中使用find()方法,則查找回來的Entity將立刻不在EntityManager的管理之中(也就是處於Detached狀態)。
* 若交易過程中發生錯誤,可以捕捉例外,執行EntityTransaction的rollback()方法來撤回交易。
EntityManager entityManager = JPAUtil.getEntityManagerFactory().createEntityManager(); EntityTransaction etx = entityManager.getTransaction(); etx.begin(); entityManager.persist(user); etx.commit(); entityManager.close();
* 若以Java EE容器來管理JPA相關資源,可以使用資源注入的方式取得EntityManager,並可由容器來為您管理Persistence Context,每個EntityManager會關聯至一個Persistence Context,容器會管理Persistence Context的存活範圍,ex: Transaction-scoped或Extended-scoped,Persistence Context管理一組Entity。
* Container-Managed EntityManager
- 使用 @PersistenceContext 注入EntityManager實例,所取得的EntityManager。
- unitName屬性指定了persistence.xml中的Persistence Context名稱,Persistence Context預設為Transaction-scoped,也就是在方法開始前會啟始交易,結束後停止交易,Persistence Context的存活範圍在交易之間。
[persistence.xml]
* transaction-type屬性為JTA,並透過
* 若要直接在Servlet中使用JPA:
- 要記得的是,EntityManager不是Thread-safe,所以切記,不可直接將EntityManager注入Servlet中成為物件成員之一,Servlet被共用存取的情況下,會有資料共用存取的問題。
- 有兩種方式:
- Container-Managed Entity: 透過在類別上宣告@PersistenceContext並設定JNDI名稱來查找。
- Application-Managed EntityManager: 透過 @PersistenceUnit 注入EntityManagerFactory並用其取得EntityManager。
* @PersistenceContext的name名稱將作為 JNDI 查找名稱,從unitName 設定得知,實際上查找到的是
* 在Java EE模組中,Persistence Unit會有個獨一無二名稱,容器會以該名稱建立EntityManagerFactory,並用其建立EntityManager,一個persistence.xml中可以定義多個Persistence Unit,以名稱作為區隔。
* 若是將 Persistence Unit 定義在 EJB-JAR 或 WAR 模組中,則 Persistence Unit 的可見範圍僅在該模組之中,若是定義在 EAR 中,則 Persistence Unit的可見範圍為整個應用程式。
* 若不使用Annotation來標註Entity類別,則可以將對應關係定義在 orm.xml 中。
* Reference
- EJB3 Gossip: 第一個 JPA (單機客戶端)
- EJB3 Gossip: 第一個 JPA(容器管理)
- EJB3 Gossip: 在 Servlet 中直接使用 JPA
- EJB3 Gossip: 部署 JPA
- Java Persistence API
- (教學簡報分享) JPA.101 JPA 簡介與教學範例
- 開源框架:Hibernate Gossip
沒有留言:
張貼留言