繁体   English   中英

JPA2.0立即提交刷新事务

[英]JPA2.0 commits transaction on flush immediatly

我在包含几个模块的项目中使用EJB3和JPA2。 最近,我注意到DB记录不会在发生异常时回滚。 经过研究后,我发现实体管理器甚至在方法结束之前就立即执行事务刷新,因此它无法在发生异常时回滚。

我注入实体管理器使用

@PersistenceContext
private EntityManager entityManager;

要创建一个新记录是在同一类中持久存在并刷新蜂鸣声

entityManager.persist(entity);
entityManager.flush();

即使我在刷新后立即调用throw New RuntimException(“”),它也不会回滚。 在调用刷新后,在调试时,我可以在方法结束之前使用数据库工具选择数据库记录。

我已经检查了persistence.xml,发现没有异常。 我不使用任何其他指定配置。 我不知道是什么原因导致这种现象。 我想任何线索。

您需要指定事务边界,否则将在每个数据操作查询(INSERT,UPDATE,DELETE)之后打开并提交新事务。 由于em.flush()会触发此类SQL查询的执行,因此它将打开一个隐式事务并在SQL成功的情况下提交该事务,如果发生错误则回滚。

为了设置事务边界并使RuntimeException触发回滚,最好的选择是从EJB对象中调用entityManager方法。 您必须使用JTA数据源 ,而不是RESOURCE_LOCAL。 如果您不使用JTA数据源,则需要自己管理事务,即。 通过使用entityManager.getTransaction()对象。

在EJB外部或具有非JTA数据源的情况下,您没有打开任何事务,除非您自己通过调用entityManager.getTransaction()。begin()来启动它。 但是,以这种方式,当抛出Exception时,您的事务将不会回滚。 相反,您必须在catch块中回滚。 在Java SE应用程序中,这大部分位于Java EE容器之外。 在Java EE中,我强烈建议使用JTA数据源。 例:

public class NotAnEJB {
  public persistEntity(EntityManager em, MyEntity entity) {
    em.getTransaction().begin();
    try {
      em.persist(entity);
      em.flush();
      if (shouldFail()) {
        throw new RuntimeException();
      }
      em.commit();
    } catch (Exception e) {
      em.rollback();
    }
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM