我使用两种测试方法运行单元测试:一种在 H2 数据库上创建实体,另一种通过某些选择标准找到它,然后将其删除。这两种方法都将所有数据库交互包装在 JTA 用户事务中(每个方法一个)。
现在在后端进行一些(未知)更改后,删除方法失败并出现乐观锁异常:
Caused by: org.hibernate.OptimisticLockException: Newer version [null] of entity [[com.example.entities.MyEntity#10001]] found in database
at org.hibernate.action.internal.EntityVerifyVersionProcess.doBeforeTransactionCompletion(EntityVerifyVersionProcess.java:54)
at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:699)
at org.hibernate.engine.spi.ActionQueue.beforeTransactionCompletion(ActionQueue.java:321)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:613)
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:122)
at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:532)
at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:235)
... 97 more
该实体有一个version
用 注释的属性@Version
。实体值是0
,并且数据库上实际上没有该实体的更新版本。finder 看起来像预期的那样工作(它找到了持久化的实体)
实际上,验证器没有找到“当前版本”。我能够通过休眠类调试我的方式,直到找到应该获取当前实体的准备好的语句(在 AbstractEntityPersister 中):
public Object getCurrentVersion(Serializable id, SessionImplementor session) throws HibernateException {
// ...
try {
PreparedStatement st = session.getTransactionCoordinator()
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( getVersionSelectString() );
try {
getIdentifierType().nullSafeSet( st, id, 1, session );
ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
try {
if ( !rs.next() ) {
return null; // <- that' where I end up. version = null
}
语句正确,id也正确,但查询结果为空。
prep68: select version from my_table where my_id =? {1: 10001}
但是现在将版本号0
与 进行比较null
,它们不相等,这会引发 OptimisticLockException。
非常欢迎任何帮助、提示、想法和解释。