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://127.0.0.1/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://127.0.0.1/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);
}
}