2

我有一个关于 JPA 的问题:有没有一种方法可以使用 JPA 2.0 的 api 来模拟 DetachedCriteria(来自 Hibernate)?

如果有一种方法我需要扩展哪些类来实现这一点?

我正在使用休眠 3.6.5 和休眠-jpa-2.0-api-1.0.0.Final。

4

1 回答 1

3

在休眠中,您在休眠会话之外创建一个 DetachedCriteria 对象,然后将其附加到稍后的会话以执行。

总之 - EJB 风格的 JPA EntityManagers(带有容器管理的 PersistenceContext)可以创建一个自动行为类似于 Hibernate DetachedCriteria 的 Query 对象,但是“核心 java”风格的 EntityManagers(即应用程序管理)永远不能创建行为类似于 Hibernate DetachedCriteria 的查询.

JPA 的 PersistenceContext 相当于一个 Hibernate Session。
JPA 的 Query 相当于一个 DetachedCriteria。
JPA EntityManager 在任何时候都可能存在也可能不存在 PersistenceContext。EntityManager 共有三种类型:

  1. 事务上下文 EM - 这种类型的 EM 只能在 SessionBean EJB 中创建 - @Stateless 或 @Stateful。PC 完全由容器管理。当没有事务正在执行时,PC 不存在。当事务开始并发生持久性操作时,PC 会自动创建并与事务一起附加和传播——每个 EM 操作都会在事务私有数据中查找 PC。交易结束时,PC 会自动清除并移除。
  2. 扩展上下文 EM - 这种类型的 EM 也只能在 SessionBean EJB 中创建 - 但只能在 @Stateful 中创建。PC 也是完全容器管理的。PC 是在 bean 启动会话会话时创建的(第一个方法从对 bean 的引用调用)。PC 附加到有状态会话 Bean 的私有数据。当会话会话的最后一个方法完成时,PC 被清除并移除(即调用了带有@Remove 标记的方法)
  3. Application Managed EM - 这种类型的 EM 可以在任何地方创建 - 在任何类型的 EJB 或在其类路径中具有 JPA 类的任何 java POJO 中。创建 EM 时创建 PC,关闭 EM 时清除和删除 PC。

在情况 (1) 和 (2) 下,EntityManager 可以随时创建查询(通过 em.createQuery() 方法)。稍后,当 PC 存在时,可以运行查询。这与 Hibernate 的行为相同。在情况 (3) 下,没有等价于 Hibernate DetachedCriteria。

不要被我在这里提到的 EJB 的事实吓到。它们非常容易实现,基本上只是添加了一些额外注释的 POJO,并且在无形中添加了一些 App Server 功能,以使它们比 POJO“更大、更快、更强”。

(2) 的一个例子:

@Stateful   
class MyStatelessEJB {    
   // Entity Manager is automatically created and injected     
   // persistent unit name is in persistence.xml
   @PersistenceContext(unitName="myPersistenceUnitName",type=PersistenceContextType.EXTENDED)   
   EntityManager em;    
   Query q1 = null;    
   Query q2 = null;

   @NOT_SUPPORTED                                     // no transaction or PC here 
   public methodA() {....                               
                      q1 = em.createQuery(...);       // create query anyway
                      q2 = em.createTypedQuery(...);
                      ...}  

   public methodB() {....  q.execute();  ...}    // transaction & PC here - just use Query

   @Remove   
   // when this method is completes the EJB Session ends    
   public methodC() {....  List<Foo> fooList = q.execute().getResultList; ...} 

}

(1) 的示例(具有事务范围 PC 的无状态会话 Bean)看起来很相似,但没有实例变量,因为它是无状态的。EntityManager & Query 必须在每个方法中创建和存储为局部变量,或者必须传递/转移到另一个可以存储它们的有状态 EJB。

于 2012-11-02T10:17:46.100 回答