OptimisticLocking在eclipse链接中不起作用

时间:2014-12-16 08:19:27

标签: java jpa eclipselink version optimistic-locking

我正在研究一个项目,由于某些问题,我正在将悲观锁定转变为乐观锁定。虽然这样做我在更新代码中的实体时遇到错误,因为我尝试将其作为独立应用程序,因此两个线程不可能同时更新它。我在代码的不同部分检查了版本的值。它显示为0.当调用flush或commit时,它给出一个例外,它被更新为1。

注意:我已在实体中添加了@version int version_id字段以进行乐观锁定。

代码如下:

            WorkItem tmp_workItem=entityManager.find(WorkItem.class , workItem.getEntityKey());

        logger.info("Before merge"+ tmp_workItem.getVersion());

        entityManager.merge(workItem);
        tmp_workItem=entityManager.find(WorkItem.class , workItem.getEntityKey());
        logger.info("After merge"+tmp_workItem.getVersion()+" "+workItem.getVersion());
        //logger.info(entityManager.getLockMode(WorkItem.class).toString());
        entityManager.flush();
        logger.info("After flush"+tmp_workItem.getVersion());
        response = true;

此代码抛出异常:

getVersion : 1
] cannot be updated because it has changed or been deleted since it was last read. 
Class> com.csg.ib.cobra.domain.WorkItem Primary Key> [9553]
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:549)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1559

记录器中的版本值为:

合并前

:0 0 合并后:0 0 在冲洗之前:0 0

然后在调用entityManger.flush()

时它如何增加1

1 个答案:

答案 0 :(得分:0)

通常,与在持久化操作上更新的id字段相比,在使用commit或flush将数据实际刷新到数据库时更新版本字段。这就是为什么在调用entityManager.flush之前版本字段值为0的原因。如果使用资源本地事务,您也可以使用transaction.commit。

关于您在应用程序代码中获得的异常,有一个更完整的代码示例(可能是JUnit测试的形式)会很有用。我创建了以下简单测试以证明正确的行为,希望它会有所帮助:

@Test
public void testOptimisticLocking() {
    OptimisticEntity entity = new OptimisticEntity();
    entity.setName("Some name");

    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();
    try {
        entityManager.persist(entity);
        transaction.commit();
    } catch (Exception x) {
        transaction.rollback();
        Assert.fail("Failed to commit: " + x.getMessage());
    }

    int id = entity.getId();
    int version = entity.getVersion();
    Assert.assertTrue(id > 0);
    Assert.assertTrue(version > 0);

    entity = entityManager.find(OptimisticEntity.class, id);
    Assert.assertNotNull("Entity could not be retrieved", entity);
    Assert.assertEquals("Entity version retrieved not expected", version, entity.getVersion());

    entity.setName("Another name");
    transaction.begin();
    try {
        entityManager.merge(entity);
        transaction.commit();
    } catch (Exception x) {
        transaction.rollback();
        Assert.fail("Failed to merge: " + x.getMessage());
    }        
    Assert.assertEquals("Entity version not incremented after merge", version+1, entity.getVersion());
}

@Test
public void testOptimisticLockingOneTransaction() {
    OptimisticEntity entity = new OptimisticEntity();
    entity.setName("Some name");

    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();
    try {
        entityManager.persist(entity);

        int id = entity.getId();
        int version = entity.getVersion();
        Assert.assertTrue(id > 0);
        Assert.assertEquals(0, version);

        OptimisticEntity retrievedEntity = entityManager.find(OptimisticEntity.class, id);
        Assert.assertNotNull("Entity could not be retrieved", retrievedEntity);
        Assert.assertEquals("Entity version retrieved not expected", 0, retrievedEntity.getVersion());

        entity.setName("Another name");
        entityManager.merge(entity);
        Assert.assertEquals("Entity version changed after merge", 0, entity.getVersion());

        retrievedEntity = entityManager.find(OptimisticEntity.class, id);
        Assert.assertNotNull("Entity could not be retrieved", retrievedEntity);
        Assert.assertEquals("Entity version retrieved not expected", 0, retrievedEntity.getVersion());

        entityManager.flush();
        Assert.assertEquals("Entity version not incremented after flush", 1, entity.getVersion());
        transaction.commit();
    } catch (Exception x) {
        transaction.rollback();
        Assert.fail("An error occurred: " + x.getMessage());
    }
}