0

我正在使用带有扩展持久性上下文的有状态会话 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. 由于 bean 级别的 @TransactionAttribute(NOT_SUPPORTED) 设置,调用 persistEntity() 方法时不会开始 txn。
  2. 一个 txn 仅在调用 commitTransaction() 方法时才开始和完成,因为它被注释为 @TransactionAttribute(REQUIRED)。

这种方法允许持久化新实体(以及它们的 ID 由 JPA 生成和自动分配,使用 @GeneratedValue),而无需 JPA 在数据库中急切地发出 INSERT stmt。因此,我可以在分配任何属性值之前立即保留实体,因为 NOT NULL 列约束尚未验证。只有在调用 commitTransaction() 方法时,JPA 才会执行 INSERT stmt 并执行 COMMIT。

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

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

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

TIA

4

1 回答 1

2

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

见,http ://en.wikibooks.org/wiki/Java_Persistence/Persisting#Flush

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

于 2012-05-09T15:01:26.227 回答