有没有办法在遇到异常时强制进行事务回滚?

时间:2014-09-29 14:47:41

标签: java hibernate ejb

当程序遇到异常时,RollBackOnly变为True。

如何将此RollBack“设置”为False即使遇到异常。

@Resource
protected SessionContext context;

Public void creerNewEntity(final Entity myEntity) {
try {
    this.em.persist(myEntity);
    this.em.flush();

    } catch (final EntityExistsException e) {
      System.out.println((this.context.getRollbackOnly())); // It s has a true value
      throw new MyException("TODO BLABLA", e);
    }
 }  

当程序抛出此异常“MyException”时,我会通过设置新ID来更改对象myEntity,然后再次调用creerNewEntity()

不幸的是,它不起作用,我得到了这个异常“javax.persistence.PersistenceException: org.hibernate.HibernateException: proxy handle is no longer valid”,我认为因为RollBack有一个真正的值,我怎样才能改变回滚以使其有效?

感谢。

2 个答案:

答案 0 :(得分:2)

可能没有一种简单的方法可以做到这一点,因为EJB设计的重点在于你不关心这些事情。事务内部的第一个错误使其无效 - >回滚。这是规则。

如果您想要一些特殊的东西,那么从会话中获取数据库连接并使用纯SQL而不是EJB来修改数据。这样,您可以尝试INSERT一个新实例并自己处理所有异常。插入成功后,您可以使用EJB加载新创建的对象以将其添加到会话中。

那就是说,我不确定你要用上面的代码实现什么。只是忽略当你无法在数据库中创建新实例时,感觉就像“我不关心我的产品的质量”。也许您尝试解决错误只是应用程序设计错误的一个症状。退后一步,考虑一下你在做什么以及为什么。也许如果你告诉我们更多关于你想忽略所有错误的原因(即使是非常致命的错误),我们也能指出更好的解决方案。

编辑所以你得到javax.persistence.EntityExistsException,这意味着你试图两次保存同一个实体。这可能意味着许多事情:

  1. 您在不同的会话中加载了bean,现在尝试将其保存在第二个会话中。由于新会话无法知道bean是否存在,因此它会尝试再次创建它。
  2. 不是像你应该那样从会话中加载bean,而是欺骗并手动创建一个新实例。当然,会话管理器现在认为这是一个新的bean。
  3. 正确的解决方案取决于您需要实现的目标。如果您修改了myEntity并需要保存更改,请使用em.merge()。然后EM将检查对象是否已经存在,如果存在,它将执行SQL UPDATE而不是INSERT

    如果您只想给其他类一个有效的实体,那么您需要从数据库中获取它。如果数据库返回null,则需要创建一个新实例并将其保留,然后将其返回。

    另请参阅:JPA EntityManager: Why use persist() over merge()?

答案 1 :(得分:0)

EntityExistsExceptionPersistenceException

当jpa抛出它时,ejb CMT被标记为回滚

http://piotrnowicki.com/2013/03/jpa-and-cmt-why-catching-persistence-exception-is-not-enough/

如aaron建议的那样,你可以使用merge()

您还可以使用RequiresNew

包含事务边界
@TransactionAttribute(REQUIRES_NEW)

http://docs.oracle.com/javaee/6/tutorial/doc/bncij.html