用于版本控制和乐观锁定的JPA 2.1时间戳记类型字段始终抛出OptimisticLockException

时间:2018-07-19 04:35:07

标签: eclipselink jpa-2.1 optimistic-locking optimistic-concurrency

环境:JPA 2.1,EclipseLink 2.6.3,SQL Server 2016

我想使用时间戳类型的字段进行版本控制和乐观。我没有选择使用数字列进行版本控制的选项。我的理解是,我只需要使用@Version以及所有这些注释字段即可。

数据库表:token_t

token_id int PK
token_name varchar(100)
last_updt_dtm datetime

Database Record

实体类

@Entity
@Table(name = "token_t")
public class TokenAE {

  @Id
  @Column(name = "token_id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int tokenId;

  @Column(name = "token_name")
  private String tokenName;

  @Version
  @Column(name = "last_updt_dtm")
  private Timestamp lastUpdtDtm;

  // getter/setter omitted to avoid cluttering
}

测试方法

@Test
public void optimisticLockingTest1() throws Exception {
    PersistenceHelper.getEntityManager().getTransaction().begin();

    TokenAE tokenAE = tokenDAO.getToken(616);
    assertNotNull("tokenAE is null", tokenAE);

    tokenAE.setTokenName("new token name");

    PersistenceHelper.getEntityManager().merge(tokenAE);

    PersistenceHelper.getEntityManager().getTransaction().commit();
}

注意-PersistenceHelper只是实例化实体管理器的助手类

如您所见,我正在加载TokenAE更新名称并进行合并。我确保基础数据库记录未更改。因此,我期望合并/更新应该成功,但是总是会引发OptimisticLockException。

请参阅下面的堆栈跟踪。我启用了JPA查询/参数日志记录,并且可以看到UPDATE查询和绑定参数。 WHERE子句[2018-07-17 22:59:48.847]中的last_updt_dtm的值与数据库记录中的值完全匹配,并且此UPDATE查询应返回rowCount 1并且应该成功。

我不知道这是怎么回事。任何帮助将不胜感激。

异常堆栈跟踪

[EL Fine]: sql: 2018-07-18 23:54:13.137--ClientSession(1451516720)--Connection(1323996324)--Thread(Thread[main,5,main])--
UPDATE token_t SET token_name = ?, last_updt_dtm = ? WHERE ((token_id = ?) AND (last_updt_dtm = ?))
    bind => [new token name, 2018-07-18 23:54:13.35, 616, 2018-07-17 22:59:48.847]
[EL Warning]: 2018-07-18 23:54:13.286--UnitOfWork(998015174)--Thread(Thread[main,5,main])--Local Exception Stack: 
Exception [EclipseLink-5006] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.OptimisticLockException
Exception Description: The object [TokenAE [tokenId=616, tokenName=new token name, lastUpdtDtm=2018-07-18 23:54:13.35]] cannot be updated because it has changed or been deleted since it was last read. 
Class> com.test.TokenAE Primary Key> 616
    at org.eclipse.persistence.exceptions.OptimisticLockException.objectChangedSinceLastReadWhenUpdating(OptimisticLockException.java:144)
    at org.eclipse.persistence.descriptors.VersionLockingPolicy.validateUpdate(VersionLockingPolicy.java:790)
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1086)
    at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
    at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:904)
    at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:803)
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1857)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1790)
    at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:273)
    at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:131)
    at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4264)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commit(UnitOfWorkImpl.java:1113)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:137)
    at sunlife.us.dc.bds.token.domain.TokenDAOTest.optimisticLockingTest1(TokenDAOTest.java:39)

0 个答案:

没有答案