JPA规范的11.1.54节指出:
通常,应用程序不应更新使用Version批注指定的字段或属性。
根据经验,我可以建议您尝试手动更新版本字段时,某些JPA提供程序(OpenJPA是其中之一)实际上会引发异常。
虽然不是严格回答您的问题,但是您可以按以下方式进行重构,以确保JPA提供程序之间的可移植性以及对JPA规范的严格遵守:
public void update(String id, Integer currentVersion) throws MyWrappedException { MyEntity myEntity = myRepository.findOne(id); if(currentVersion != myEntity.getVersion()){ throw new MyWrappedException(); } myRepository.save(myEntity); //still an issue here however: see below}假设您的
update(...)方法正在事务中运行,但是如JPA规范第3.4.5节所述,您仍然遇到上述问题:
3.4.5
OptimisticLockException与有效的锁定模式和刷新模式设置一致时,提供程序实现可以将对数据库的写操作推迟到事务结束。在这种情况下,直到提交时间才可能进行乐观锁检查,并且可能在提交的“完成之前”阶段引发OptimisticLockException。
如果OptimisticLockException必须由应用程序捕获或处理,则应用程序应使用flush方法来强制执行数据库写操作。
这将允许应用程序捕获和处理乐观锁异常。
基本上,两个用户可以同时提交同一实体的修改。这两个线程都可以通过初始检查,但是当更新被刷新到数据库时可能会失败,这可能是在事务提交时执行的,即在您的方法完成之后。
为了可以捕获和处理OptimisticLock异常,代码应如下所示:
public void update(String id, Integer currentVersion) throws MyWrappedException { MyEntity myEntity = myRepository.findOne(id); if(currentVersion != myEntity.getVersion()){ throw new MyWrappedException(); } myRepository.save(myEntity); try{ myRepository.flush() } catch(OptimisticLockingFailureException ex){ throw new MyWrappedException(); }}


