CacheId aci = new CacheId();
aci.setId(cacheObject.getId());
aci.setSequence(cacheObject.getSequence());
Cache persisted = em.find(Cache.class, aci);
if (persisted == null){
System.out.println("========== PERSISTING");
em.persist(cacheObject);
}else{
System.out.println("========== MERGING");
em.merge(cacheObject);
}
在运行我的项目时,另一个实例删除具有当前CacheId的条目。现在我需要做的是将新值设置为具有相同缓存ID的数据库。但是当我执行em.find()时,这不会返回null。 (但是在数据库条目中已经删除。所以这最终会调用merge。并且尝试更新1但是更新了0 ...
但是如果我停止检查搜索并且呼叫持续存在,那么我得到"分离的实体传递给持续#34;。我该如何解决这个问题?
答案 0 :(得分:0)
您遇到并发访问问题,答案是锁定。如果在应用程序中使用乐观锁定,只需捕获异常并重试(有限数量或多次)。
您还可以使用:
来使用悲观锁定模式Cache persisted = em.find(Cache.class, aci, LockModeType.PESSIMISTIC_WRITE);
(或LockModeType.PESSIMISTIC_READ
)。锁定是从数据库中立即获得的,即如果数据已被删除,您将立即知道。一旦获得锁定,就不允许其他任何交易将其删除。
唯一剩下的竞争条件是如果两个事务尝试创建相同的数据。
但请注意:应用程序应尽快提交以释放锁定,以避免潜在的死锁或不必要的其他事务阻塞。