[英]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.