在提交之前,查询不会检索持久化实体

时间:2012-05-08 19:11:57

标签: caching jpa ejb

我正在使用带有EXTENDED持久化上下文的有状态会话bean,以及以下@TransactionAttribute设置:

@Stateful(...)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class StatefulExtendedEJBBea {
    @PersistenceContext(unitName = "JPAModel", type = PersistenceContextType.EXTENDED)
    private EntityManager em;

    ...

    /**
     * With the REQUIRED txn attribute, we can ensure that each time
     * this method is called a new transaction is created and any
     * pending changes in the persistence context are committed.
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void commitTransaction() {
    }

    /** <code>select o from Departments o</code> */
    public List<Departments> getDepartmentsFindAll() {
        return em.createNamedQuery("Departments.findAll").getResultList();
    }

    public <T> T persistEntity(T entity) {
        em.persist(entity);
        return entity;
    }
 }

在这个例子中要提出一些重要的事情:

  1. 调用persistEntity()方法时,txn未启动, 因为bean级别@TransactionAttribute(NOT_SUPPORTED) 设置。
  2. 只有当txn开始并完成时才会 调用commitTransaction()方法,因为它是注释的 @TransactionAttribute(必需)。
  3. 这种方法允许新实体被持久化(并且它们的ID由JPA生成并使用@GeneratedValue自动分配),而JPA并不急切地在DB中发布INSERT stmt。因此,在分配任何属性值之前,我可以立即持久保存实体,因为尚未验证NOT NULL列约束。只有在调用commitTransaction()方法时,JPA才会执行INSERT stmt并执行COMMIT。

    现在,有很多似乎按照我的预期工作,具有上面列出的好处。我遇到的问题是我无法通过JPQL查询检索新的持久化实体,直到调用commitTransaction()为止。新持久化实体似乎由持久化上下文管理,因为我可以在调用persistEntity()之后继续更新它们,并且当我调用commitTransaction()时,所有后续更改都会正确保存到数据库中。但是,在我发出提交之前,它们似乎不在查询缓存中。

    我猜我在提交时间之前抑制txn的策略会以某种方式影响查询结果。

    是否有一个查询提示我可以用来强制持久化(在事务之外)但未提交的实体要包含在JPQL查询中?

    TIA

1 个答案:

答案 0 :(得分:1)

您可以在提交之前调用flush()将更改写入数据库。

请参阅http://en.wikibooks.org/wiki/Java_Persistence/Persisting#Flush

EntityManager上还有一个刷新模式,它会在每个查询之前触发刷新,默认为auto,所以很奇怪你看不到新对象。也许您正在为查询使用不同的事务?在这种情况下,另一个事务永远不会看到另一个事务的未提交的更改,即事务的那种点。