我遇到一个问题,即当EJB层引发OptimisticLockException时,如何在Web层(.war代码)中捕获它。
我们使用的是JEE5,GlassFishV2.1和JPA(以及TopLinks)和容器托管事务,但是当脏读是由于另一个并发用户在同一实体上的交易而发生的时,会在战争层产生Transaction.RollBackException,这实际上是导致但是我无法在战争方面赶上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,然后重试。有更好的选择吗?
尝试{
//一些代码
}
捕获(EJBException ex){
if (ex.getCausedByException().getCause().toString().
indexOf("javax.transaction.RollbackException")!= -1){
// do work
}
}
}
最佳答案
你可以做。 flush()从技术上讲并不是昂贵的操作,因为它不再需要通过提交来完成写入数据库的工作,因此没有额外的数据库访问权限,也不会“刷新所有数据库”。尽管flush()确实有一些开销,但是更改将被计算两次,一次是刷新,一次是提交,一次是提交。根据您的更改策略和托管对象的数量,这确实需要一定的成本。刷新还需要将受管对象放回跟踪的受管状态,这也要付出一些代价,但与数据库访问成本相比通常较小。
请注意,在提交期间可能会发生除锁定错误以外的其他错误,因此,即使您使用刷新来捕获锁定错误,您在战争中仍然需要代码来处理其他失败原因,因此不要使用刷新,而只是使用一般事务失败的错误处理可能是最好的解决方案。如果要对锁定错误进行特殊处理,则应该能够按原因查找异常,但是在重试该操作时要小心,因为锁定是有原因的,因此应该将错误报告给用户并让他们重试其操作。
关于java - 如何在Web层中捕获OptimisticLockException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3820883/