Java 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

嗨,我正在与JPA2上的乐观锁定作斗争,我不知道为什么会发生这种情况。 我的情况是,我正在运行多个线程,但数据库中有一个实体存储进度。这意味着不同的线程试图在执行期间更新该实体,以便能够按用户查看进度

我有一个方法
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);