Jpa 使用实体管理器处理异常
我听说在使用实体管理器提交事务时,如果提交失败,最好再试一次,因为在事务处理过程中对象可能会发生更改 这看起来像是一个正确的重试实现吗Jpa 使用实体管理器处理异常,jpa,entitymanager,Jpa,Entitymanager,我听说在使用实体管理器提交事务时,如果提交失败,最好再试一次,因为在事务处理过程中对象可能会发生更改 这看起来像是一个正确的重试实现吗 int loopCount = 1; boolean transactionCommited = false; while(!transactionCommited && loopCount <3) { EntityManager em = EMF.getInstance().getEntityManager(); try
int loopCount = 1;
boolean transactionCommited = false;
while(!transactionCommited && loopCount <3) {
EntityManager em = EMF.getInstance().getEntityManager();
try{
EntityTransaction tx = em.getTransaction();
tx.begin();
Player playerToEdit = em.find(Player.class, id);
playerToEdit.setLastName(lastName);
tx.commit();
transactionCommitted = true;
} catch(Exception e){
if(loopCount == 2){
//throw an exception, retry already occurred?
}
} finally{
if(tx.isActive()){
tx.rollback();
}
em.close();
}
loopCount++;
}
int loopCount=1;
布尔TransactionCommitted=false;
当(!TransactionCommitted&&loopCount在catch块中缓存“Exception”时,在无法完成更新的情况下,您正在重试更新。例如,如果在数据库中找不到实体,您将尝试查找它两次
您应该捕获最具体的异常“OptimisticLockException”。当实体的版本与数据库中存储的版本不匹配时,会引发此异常。实体中的版本字段是实现此锁定策略的必要条件
在高并发应用程序中还可以使用其他锁定策略,但大多数情况下,乐观锁定策略是最合适的
作为一个小细节,使用常量作为重试次数,而不是“幻数”提高了代码的可读性,并且以后更容易修改重试次数。通常,再次提交相同的更改是一个坏主意。即使引发的异常是OptimisticLockException
,这也不是一个好主意,因为这可能意味着某人正在覆盖某人所做的更改。想象一下以下场景:
用户1更改entityX并提交它
用户2更改同一entityX的a部分字段并尝试提交它。EntityManager
引发异常
正确的场景是在这里向用户指示异常,以便他重新读取实体并重试相同的修改
现在最重要的论点是为什么这是危险的:
至少Hibernate知道,如果在抛出异常后尝试重用EntityManager
,可能会发生不好的事情。在数据损坏或应用程序停止正常工作之前,请查看或。在循环中,正如您所建议的,我正在通过调用Player playerToEdit=em.find(Player.class,id)进行读取;正确?是的,您正在重新读取。但是用户2没有看到这些更改(来自用户1),因此它只会覆盖user1!的更改。那么,在处理EntityManager时,我应该捕获什么类型的异常,以确保捕获到任何与jpa/持久性相关的内容?@AndreiI请您看看这个问题?如果用户2在ser 1完成了他们的提交,对吗?