【问题标题】:JPA2 Optimistick LockJPA2 乐观锁
【发布时间】:2014-09-01 19:28:21
【问题描述】:

您好,我正在为 JPA2 上的 Optimistick Lock 苦苦挣扎,我不知道为什么会发生这种情况。 我的情况是我正在运行多个线程,但数据库中有一个实体存储进度。这意味着不同的线程在执行期间尝试更新此实体,以便可以查看用户的进度。

我有一个方法addAllItemsaddDone。这两种方法都用于通过多个线程更新实体,我通过显示(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);
}

当我意识到 Optimistic Lock 正在发生时,我通过在签名中添加同步来更改这两种方法。它没有效果,所以我添加了刷新(来自实体管理器)以确保我拥有当前版本。它也没有任何区别。最后我还添加了手动冲洗,但仍然没有更好的...

这里是方法的最终版本(addAllItems 几乎相同,只是在 setter 中有所不同):

@Transactional(propagation=Propagation.REQUIRES_NEW)
public synchronized void addDone(Long id, Integer done){
    Job job = jobDao.findById(id);
    job = jobDao.refresh(job);
    job.setDone(job.getDone() + done);

    jobDao.merge(job);
    jobDao.flush();
}

jobDao.refresh 方法只是在 entityManager 上调用刷新。 我正在使用 eclipselink 2.40。

我还能检查什么? 我暂时没有想法......

【问题讨论】:

  • 我正在努力,但截止日期非常接近,所以我正在寻找更有经验的人的帮助。我认为这就是创建 stackoverflow 的原因。如果您不想回答,请不要回答。
  • 或许你应该对工作使用悲观锁?
  • 错误发生在哪个实体上?真的Job 吗?你能在Job中显示什么是alldone
  • @SergeBallesta Job 实体发生错误。 all 和 done 只是整数。这是一条日志行:javax.persistence.OptimisticLockException: Exception [EclipseLink-5006] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.OptimisticLockException Exception Description: The object [com.hg.entity.Job@98] cannot be updated because it has changed or been deleted since it was last read. Class> com.hg.entity.Job Primary Key> 152
  • 您应该首先确保您确实使用了事务代理(查看堆栈跟踪),然后使用悲观锁

标签: java spring eclipselink jpa-2.0 optimistic-locking


【解决方案1】:

由于您确定您使用的是代理(我假设您正确配置了PlatformTransactionManager),您可以尝试在事务中使用显式悲观锁 - 通常您不需要这样做,但如果它解决问题...

我想在你的 dao 中,你有类似的东西:

Job job = EntityManager.find(Job.class, jobId);

要强制悲观锁,只需将其更改为:

Job job = EntityManager.find(Job.class, jobId, LockModeType.PESSIMISTIC_WRITE);

当您只是加载、修改、存储和提交时,它可能是悲观锁定的正确用例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 2011-02-23
    • 2013-06-30
    • 1970-01-01
    • 2018-03-29
    相关资源
    最近更新 更多