如何在Web层中捕获OptimisticLockException

时间:2010-09-29 10:50:56

标签: java jpa ejb-3.0 optimistic

我遇到的一个问题是如何在EJB层引发Web层(.war代码)时捕获OptimisticLockException。

我们正在使用JEE5,GlassFishV2.1和JPA(带有TopLinks)和容器管理事务。但是当由于同一实体上的另一个并发用户的trnasaction而发生脏读时。它在war层给出了Transaction.RollBackException。实际上是由OptimisticLockException引起的。但我无法在战争端捕获OptimisticLockException。

我在互联网上找到了 http://books.google.com/books?id=fVCuB_Xq3pAC&pg=PA292&dq=OptimisticLockException++Collision+Exception&hl=en&ei=0A6jTI3nN5DQccbO5MAB&sa=X&oi=book_result&ct=result&resnum=1&ved=0CCgQ6AEwAA#v=onepage&q=OptimisticLockException%20%20Collision%20Exception&f=false

在ejb方面使用em.flush然后我们可以捕获并向战争抛出一些自定义异常。 但我认为em.flush会刷新所有数据库,这是否是一项昂贵的操作?

try{
   //some enitity
   em.flush()
  }
catch(OptimisticLockException ole){

throw ole;
}

我的意见是不要调用em.flush,因为90%的情况下不存在OptimisticLockException并且在.war中捕获EJBException然后重试它。有更好的选择吗?

尝试{             //一些代码         }        catch(EJBException ex){

      if (ex.getCausedByException().getCause().toString().
          indexOf("javax.transaction.RollbackException")!= -1){
               // do work
          }     
      }
   }

1 个答案:

答案 0 :(得分:1)

你可以做任何一件事。 flush()在技术上并不是一项昂贵的操作,因为它在写入数据库时​​所做的工作不再需要通过提交来完成,因此没有额外的数据库访问,也没有“刷新所有数据库”。 flush()确实有一些开销,更改将计算两次,一次用于刷新,一次用于提交,一次用于提交。根据您的更改策略和托管对象的数量,这确实有成本。 Flush还需要将托管对象重新置于跟踪的托管状态,这也需要一些成本,但与数据库访问成本相比通常较小。

请注意,在提交期间可能会发生其他错误而不是锁定错误,因此即使您使用刷新来捕获锁定错误,您仍然需要在战争中使用代码来处理其他失败原因,因此不使用flush,只是让一般事务失败错误处理可能是最好的解决方案。如果你想为锁定错误做一些特别的事情,你应该能够在原因中找到异常链,但是在重试操作时要小心,你是因为某个原因而锁定的,所以应该把错误报告给用户让他们重试他们的操作。