Java JPA2.0在刷新时立即提交事务

Java JPA2.0在刷新时立即提交事务,java,jpa,commit,entitymanager,flush,Java,Jpa,Commit,Entitymanager,Flush,我在一个包含几个模块的项目中使用EJB3和JPA2。 最近我注意到DB记录不会在异常时回滚。在做了一些研究之后,我发现实体管理器甚至在方法结束之前就立即在flush上提交事务,所以它不能在异常时回滚 我使用 @PersistenceContext private EntityManager entityManager; 在同一个类中调用persist和flush being来创建新记录 entityManager.persist(entity); entityManager.flush();

我在一个包含几个模块的项目中使用EJB3和JPA2。 最近我注意到DB记录不会在异常时回滚。在做了一些研究之后,我发现实体管理器甚至在方法结束之前就立即在flush上提交事务,所以它不能在异常时回滚

我使用

@PersistenceContext
private EntityManager entityManager;
在同一个类中调用persist和flush being来创建新记录

entityManager.persist(entity);
entityManager.flush();
即使我在刷新之后立即调用thrownewruntimexception(“”),它也不会回滚。在调用flush之后进行调试时,我可以在方法结束之前使用数据库工具选择DB记录

我已经检查了persistence.xml,没有发现任何异常。我不使用任何其他指定的配置。
我不知道是什么导致了这种行为。我会通知您任何线索。

您需要指定事务边界,否则在每次数据操作查询(插入、更新、删除)后将打开并提交新事务。由于
em.flush()
将触发执行此类SQL查询,因此如果SQL成功,它将打开一个隐式事务并提交它,如果出现错误则回滚

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

在EJB之外,或者对于非JTA数据源,您不会打开任何事务,除非您自己通过调用entityManager.getTransaction().begin()来启动它。然而,通过这种方式,当抛出异常时,您的事务不会回滚。相反,您必须在挡块中向后滚动。这主要在JavaEE容器之外,在JavaSE应用程序中。在JavaEE中,我强烈建议使用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();
    }
  }
}

你能再次检查自动提交吗?非常感谢kervin。这就是解决办法。我仍然不明白为什么会发生这种行为,但我会阅读一些文档。