【问题标题】:JPA EntityManager.flush() is not called by java/jakarta EE containerjava/jakarta EE 容器不调用 JPA EntityManager.flush()
【发布时间】:2020-11-26 00:33:53
【问题描述】:

glassfish 5.1 EE 容器不调用 JPA EntityManager.flush()。

在 Java SE 环境中:

EntityTransaction t = em.getTransaction();
t.begin();

// persist entities
em.persist(entity);

t.commit();

commit() 将刷新持久化上下文中的实体。

Java EE 环境,例如玻璃鱼:

@Stateless
public class DataManagerBean {
    @PersistenceContext
    EntityManager em;

    public void persist(Object entity) {
        em.persist(entity);
    }
}

JSF 豆:

@Named
@ViewScoped
public class FooBean  {
    @EJB
    DataManagerBean dataManagerBean;
    
    public void createFoo() {
        dataManagerBean.persist(foo);       
    }
} 

应用程序不能调用 em.getTransaction()。事务由容器管理。在调用 entityManager.close() 之前,不调用 JPA 提供程序 entityManager.flush()。因此,实体没有在数据库中创建。

在EE环境下,JPA提供者EntityManager获取的数据库连接和容器使用的一样吗?

如果不调用 flush(),EE 容器如何告诉 JPA 提供者刷新实体以持久化?

【问题讨论】:

  • 谁在打电话DataManagerBean
  • JSF 托管 bean
  • “事务由容器管理” 您对此有何把握?您的实际问题表明情况并非如此。
  • 从调试来看,使用 Glassfish EntityManagerWrapper 和 JavaEETransactionManagerSimplified 代替 JPA 提供者 EntityTransaction。

标签: jpa jakarta-ee java-ee-8


【解决方案1】:

这取决于您调用业务方法的方式。简而言之,beeing 默认——事务从您的流程进入第一个业务方法(或拦截器,装饰您的第一个业务方法)开始,并在您的流程离开堆栈中的最后一个业务方法(或拦截器,装饰您的第一个业务方法)时结束。

您可以使用带有适当TransactionAttributeType@TransactionAttribute 注释管理事务(如果未注释,则默认为REQUIRED)。例如:

@Stateless
public class DataManagerBean {
    @PersistenceContext
    EntityManager em;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void persist(Object entity) {
        em.persist(entity);
    }
}

在这种情况下,调用 DataManagerBean.persist 会启动新事务并在离开时提交和刷新更改。如果发生错误,它将回滚事务并抛出异常,您可以在调用业务方法时捕获。

【讨论】:

  • 试过 default(REQUIRED) 和 TransactionAttributeType.REQUIRES_NEW,entityManager.flush() 在这两种情况下都没有被容器调用。
  • 奇怪的行为。实际上 dataManagerBean.persist(foo) 中的 foo 应该是有效的实体实例。是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 2023-01-03
  • 2021-01-19
  • 1970-01-01
  • 2013-03-30
  • 2021-04-14
  • 2013-06-15
相关资源
最近更新 更多