Java JPA2自动打钩锁
嗨,我正在与JPA2上的乐观锁定作斗争,我不知道为什么会发生这种情况。 我的情况是,我正在运行多个线程,但数据库中有一个实体存储进度。这意味着不同的线程试图在执行期间更新该实体,以便能够按用户查看进度 我有一个方法Java JPA2自动打钩锁,java,spring,eclipselink,jpa-2.0,optimistic-locking,Java,Spring,Eclipselink,Jpa 2.0,Optimistic Locking,嗨,我正在与JPA2上的乐观锁定作斗争,我不知道为什么会发生这种情况。 我的情况是,我正在运行多个线程,但数据库中有一个实体存储进度。这意味着不同的线程试图在执行期间更新该实体,以便能够按用户查看进度 我有一个方法addAllItems和addDone。这两种方法都通过几个线程来更新实体,我通过显示(done/allItems)*100来显示结果 方法一开始很简单 @Transactional(propagation=Propagation.REQUIRES_NEW) public void a
addAllItems
和addDone
。这两种方法都通过几个线程来更新实体,我通过显示(done/allItems)*100来显示结果
方法一开始很简单
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void addAllItems(Long id, Integer items){
Job job = jobDao.findById(id);
job.setAll(job.getAll() + items);
jobDao.merge(job);
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void addDone(Long id, Integer done){
Job job = jobDao.findById(id);
job.setDone(job.getDone() + done);
jobDao.merge(job);
}
当我意识到乐观锁正在发生时,我通过在签名中添加synchronized更改了这两种方法。它没有效果,所以我添加了刷新(从实体管理器)以确保我使用的是当前版本。这也没什么区别。最后我还添加了手动刷新,但仍然没有更好的
这里是方法的最终版本(addAllItems
基本相同,唯一的区别在于setter):
其中,jobDao.refresh
方法只是在entityManager
上调用refresh。
我用的是eclipselink 2.40
我还能查什么?
我现在没有主意了…因为您确信您正在使用代理(我假设您正确配置了平台TransactionManager
),您可以尝试在事务中使用显式悲观锁-通常您不需要这样做,但如果它解决了问题
我想在你的刀里,你有这样的东西:
Job job = EntityManager.find(Job.class, jobId);
要强制执行悲观锁定,只需将其更改为:
Job job = EntityManager.find(Job.class, jobId, LockModeType.PESSIMISTIC_WRITE);
由于您只需加载、修改、存储和提交,因此它可能是悲观锁定的正确用例。我正在研究它,但截止日期很近,因此我正在寻求更有经验的人的帮助。我想这就是stackoverflow被创建的原因。如果您不想回答,请不要回答。也许您应该在作业上使用悲观锁?错误发生在哪个实体上?真的是工作
?能否显示作业
@中的全部
和完成
是什么?作业实体上发生错误。所有的和完成的都是整数。下面是一个日志行:javax.persistence.OptimisticLockException:Exception[EclipseLink-5006](Eclipse持久性服务-2.4.0.v20120608-r11652):org.Eclipse.persistence.exceptions.OptimisticLockException描述:对象[com.hg.entity]。Job@98]无法更新,因为自上次读取后已更改或删除。Class>com.hg.entity.Job主键>152
您应该首先确保使用事务代理(查看stacktrace),然后使用悲观锁
Job job = EntityManager.find(Job.class, jobId, LockModeType.PESSIMISTIC_WRITE);