我正在使用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()现在可以对其进行检索
答案 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。