Java 持久化/執行時
在對映完物件模型後,持久化開發的第二步是從應用程式訪問和處理物件,這被稱為持久化的執行時使用。各種持久化規範都有不同的執行時模型。最常見的模型是擁有一個執行時 API;執行時 API 通常會定義 API 用於連線到資料來源、查詢和事務。
JPA 提供了由 javax.persistence 包定義的執行時 API。主要的執行時類是 EntityManager 類。EntityManager 提供用於建立查詢、訪問事務以及查詢、持久化、合併和刪除物件的 API。JPA API 可用於任何 Java 環境,包括 JSE 和 JEE。
EntityManager 可以透過 EntityManagerFactory 建立,也可以注入到 EJB SessionBean 中的例項變數中,也可以在 JEE 伺服器中的 JNDI 中查詢。
JPA 在 Java 標準版 (JSE) 和 Java 企業版 (JEE) 中的使用方式不同。
在 Java SE 中,EntityManager 是透過 JPA Persistence 類中的 createEntityManagerFactory API 訪問的。持久化單元名稱 傳遞給 createEntityManagerFactory,這是在持久化單元的 persistence.xml 檔案中給定的名稱。所有 Java SE JPA 應用程式都必須定義 persistence.xml 檔案。該檔案定義了持久化單元,包括名稱、類、orm 檔案、資料來源、特定於供應商的屬性。
JPA 1.0 沒有定義在 Java SE 中指定如何連線到資料庫的標準方法。每個 JPA 提供商都定義了自己的持久化屬性,用於設定 JDBC 驅動程式管理器類、URL、使用者和密碼。JPA 有一種標準方法來設定 DataSource JNDI 名稱,但這主要用於 JEE。
JPA 2.0 在 Java SE 中定義了用於連線到 JDBC 的標準持久化單元屬性。這些包括 javax.persistence.jdbc.driver、javax.persistence.jdbc.url、javax.persistence.jdbc.user、javax.persistence.jdbc.password。
JPA 應用程式通常需要打包到持久化單元 jar 檔案中。這是一個普通的 jar 檔案,它在 META-INF 目錄中包含 persistence.xml 檔案。通常,JPA 提供商會要求在 Java SE 中執行一些特殊操作來啟用某些功能,例如延遲獲取,例如 jar 的靜態編織(位元組碼處理),或使用 Java 代理 JVM 選項。
在 Java SE 中,當您的應用程式不再使用 EntityManager 時,必須關閉它。EntityManager 的生命週期通常是每個客戶端或每個請求。EntityManagerFactory 可以由多個執行緒或使用者共享,但 EntityManager 不應該共享。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd"
version="1.0">
<persistence-unit name="acme" transaction-type="RESOURCE_LOCAL">
<!-- EclipseLink -->
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- TopLink Essentials -->
<!--provider>oracle.toplink.essentials.PersistenceProvider</provider-->
<!-- Hibernate 3.x -->
<!--provider>org.hibernate.ejb.HibernatePersistence</provider-->
<!-- Hibernate -->
<!--provider>org.hibernate.jpa.HibernatePersistenceProvider</provider-->
<!-- Apache OpenJPA -->
<!--provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider-->
<!-- DataNucleus-->
<!--provider>org.datanucleus.jpa.PersistenceProviderImpl</provider-->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.jdbc.driver" value="org.acme.db.Driver"/>
<property name="eclipselink.jdbc.url" value="jdbc:acmedb:///acme"/>
<property name="eclipselink.jdbc.user" value="wile"/>
<property name="eclipselink.jdbc.password" value="elenberry"/>
</properties>
</persistence-unit>
</persistence>
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd"
version="2.0">
<persistence-unit name="acme" transaction-type="RESOURCE_LOCAL">
<!-- EclipseLink -->
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- TopLink Essentials -->
<!--provider>oracle.toplink.essentials.PersistenceProvider</provider-->
<!-- Hibernate 3.x -->
<!--provider>org.hibernate.ejb.HibernatePersistence</provider-->
<!-- Hibernate -->
<!--provider>org.hibernate.jpa.HibernatePersistenceProvider</provider-->
<!-- Apache OpenJPA -->
<!--provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider-->
<!-- DataNucleus -->
<!--provider>org.datanucleus.jpa.PersistenceProviderImpl</provider-->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.acme.db.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:acmedb:///acme"/>
<property name="javax.persistence.jdbc.user" value="wile"/>
<property name="javax.persistence.jdbc.password" value="elenberry"/>
</properties>
</persistence-unit>
</persistence>
EntityManagerFactory factory = Persistence.createEntityManagerFactory("acme");
EntityManager entityManager = factory.createEntityManager();
...
entityManager.close();
在 Java EE 中,EntityManager 或 EntityManagerFactory 可以透過在 JNDI 中查詢或注入到 SessionBean 中來獲取。要在 JNDI 中查詢 EntityManager,它必須釋出到 JNDI 中,例如透過 SessionBean 的 ejb-jar.xml 檔案中的 <persistence-context-ref>。要注入 EntityManager 或 EntityManagerFactory,使用 @PersistenceContext 或 @PersistenceUnit 註解。
在 Java EE 中,EntityManager 可以是管理的(容器管理的)或非管理的(應用程式管理的)。管理的 EntityManager 與應用程式管理的 EntityManager 具有不同的生命週期。管理的 EntityManager 不應該關閉,並且與 JTA 事務整合,因此不能使用本地事務。在每個 JTA 事務邊界,透過管理的 EntityManager 讀取或持久化的所有實體都會變為分離狀態。在 JTA 事務之外,管理的 EntityManager 的行為有時很奇怪,因此通常應該在 JTA 事務中使用它。
非管理的 EntityManager 是指透過 EntityManagerFactory 或直接從 Persistence 建立的 EntityManager。非管理的 EntityManager 必須關閉,並且通常不與 JTA 整合,但這可以透過 joinTransaction API 來實現。非管理的 EntityManager 中的實體在事務完成後不會變為分離狀態,並且可以在隨後的事務中繼續使用。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd"
version="1.0">
<persistence-unit name="acme" transaction-type="JTA">
<jta-data-source>jdbc/ACMEDataSource</jta-data-source>
</persistence-unit>
</persistence>
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
<enterprise-beans>
<session>
<ejb-name>EmployeeService</ejb-name>
<business-remote>org.acme.EmployeeService</business-remote>
<ejb-class>org.acme.EmployeeServiceBean</ejb-class>
<session-type>Stateless</session-type>
<persistence-context-ref>
<persistence-context-ref-name>persistence/acme/entity-manager</persistence-context-ref-name>
<persistence-unit-name>acme</persistence-unit-name>
</persistence-context-ref>
<persistence-unit-ref>
<persistence-unit-ref-name>persistence/acme/factory</persistence-unit-ref-name>
<persistence-unit-name>acme</persistence-unit-name>
</persistence-unit-ref>
</session>
</enterprise-beans>
</ejb-jar>
InitialContext context = new InitialContext(properties);
EntityManager entityManager = (EntityManager)context.lookup("java:comp/env/persistence/acme/entity-manager");
...
InitialContext context = new InitialContext(properties);
EntityManagerFactory factory = (EntityManagerFactory)context.lookup("java:comp/env/persistence/acme/factory");
...
@Stateless(name="EmployeeService", mappedName="acme/EmployeeService")
@Remote(EmployeeService.class)
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName="acme")
private EntityManager entityManager;
@PersistenceUnit(unitName="acme")
private EntityManagerFactory factory;
...
}
(對 審計 有用)
protected EJBContext getContext() {
try {
InitialContext context = new InitialContext();
return (EJBContext)context.lookup("java:comp/EJBContext");
} catch (NamingException e) {
throw new EJBException(e);
}
}