悲观锁定中的OptimisticLockException

时间:2014-12-08 11:16:55

标签: java spring hibernate java-ee

我正在使用Spring和Hibernate。我正在运行这样的jUnit测试:

String number = invoiceNumberService.nextInvoiceNumber();

和invoiceNumberService方法是:

InvoiceNumber invoiceNumber = invoiceNumberRepository.findOne(1L);

它使用简单的spring数据存储库方法,并且运行良好。但是,当我重写此方法以使用锁定时:

@Lock(LockModeType.PESSIMISTIC_READ)
@Override
InvoiceNumber findOne(Long id);

我收到“javax.persistence.OptimisticLockException:Row被另一个事务更新或删除”

我无法理解为什么它的乐观锁定异常,而我使用的是悲观锁定?当另一个交易正在改变这个实体时,这个部分在哪里? 我已经挖了很多类似的问题,我非常绝望。谢谢你的帮助

解决方案:
问题在于我在测试类中的init函数:

@Before
public void init() {
    InvoiceNumber invoiceNumber = new InvoiceNumber(1);
    em.persist(invoiceNumber);
    em.flush();
}

缺乏

em.flush();

将数据保存到数据库中,因此findOne()现在可以对其进行检索

2 个答案:

答案 0 :(得分:0)

问题:您是否在dao或服务层中提供了@transcational注释? 它发生的原因是两个事务同时试图改变同一个表的数据。所以如果从dao层中删除所有注释并放入服务层,它应该解决我的问题...因为我遇到了类似的问题。 希望能帮助到你。

答案 1 :(得分:0)

为了它,我会发布以下内容,如果有人不同意请纠正我。一般在java中,建议使用Spring / hibernate和JPA。 Hibernate实现了JPA,因此您需要Spring和Hibernate的依赖项。

接下来让Spring / hibernate管理你的事务和提交部分。自己刷新/提交数据是不好的做法。

例如,假设以下方法:

public void changeName(long id, String newName) {
   CustomEntity entity = dao.find(id);
   entity.setName(newName);
}

此方法后不会发生任何事情(您可以调用merge和commit)。但是如果你用@Transactional注释它,你的实体将被管理,并且在@Transactional方法结束时,Spring / hibernate将提交你的更改。所以这就足够了:

@Transactional
public void changeName(long id, String newName) {
   CustomEntity entity = dao.find(id);
   entity.setName(newName);
}

无需调用flush,Spring / Hibernate将为您处理所有混乱。只是不要忘记你的测试必须调用@Transactional方法,或者自己应该是​​@Transactional。