2012-07-30 20 views
1

也许这个问题已经被证实,可能不是。如何在使用JPA和OPTIMISTIC锁时自动刷新版本字段? (EclipseLink)

我想更新与乐观锁的对象,使用

... 
EntityManager.merge(...); 
EntityManager.flush(...); 
... 

我的代码工作正常。我想要的是更新对象中的版本号并保留对象引用。

我用google搜索了很长时间,但没有找到答案。

我最后的手段是make nativeQuery并获取版本号。

下面是一个测试代码:

EntityManagerFactory factory = Persistence.createEntityManagerFactory(DBManager.getUnidadPersistencia()); 
    EntityManager emA = factory.createEntityManager(); 

    Grupo g = emA.find(Grupo.class, 1L); 

    emA.close(); 

    //In some place 
    g.getSolicitanteList().get(0).setObservaciones("ZZZZ"); //Originally XXXX 

    //... 


    //Then I have to save the changes 
    EntityManager emB = factory.createEntityManager(); 
    EntityTransaction tx = emB.getTransaction(); 

    try { 
     tx.begin(); 
     emB.merge(g); 
     emB.flush(); 
     tx.commit(); 
     //Here comes exception 
     emB.refresh(g); 
    } catch (Exception e) { 
     if (tx.isActive()) { 
      tx.rollback(); 
     } 
     logger.log(Level.SEVERE, null, e); 
    } 
    emB.close(); 

而且堆栈跟踪:

30/07/2012 05:15:31 PM org.rp.co5parser.TestGrupo refreshTest 
GRAVE: null 
java.lang.IllegalArgumentException: Can not refresh not managed object: org.rp.co5parser.alojamiento.Grupo[ idGrupo=1 ]. 
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.refresh(EntityManagerImpl.java:943) 
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.refresh(EntityManagerImpl.java:849) 
at org.rp.co5parser.TestGrupo.refreshTest(TestGrupo.java:89) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
at org.apache.tools.ant.taskdefs.optional.junit.JUnit4TestMethodAdapter.run(JUnit4TestMethodAdapter.java:109) 
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:520) 
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1060) 
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:911) 

可以吗?

在此先感谢....

回答

3

谷歌搜索之前,请阅读the documentation

无效刷新(java.lang.Object继承实体)

从数据库中刷新实例的状态,覆盖对实体所做的更改(如果有的话)。

编辑:

你得到的错误是不是OptimisticLockException。这是一个IllegalArgumentException,并有一个非常明确的错误消息:无法刷新未管理对象。您只能刷新被管理的实体。你传递的对象是一个分离的对象。

如果您不忽略merge()的结果,则根本不需要刷新实体。 merge()需要分离的对象,将其状态复制到具有相同ID的托管(附加)对象,并返回管理对象。所以你应该只需要做:

try { 
    tx.begin(); 
    g = emB.merge(g); // assign the merged, attached object, having the new version to g 
    tx.commit(); // no need to flush. commit flushes automatically 
} catch (Exception e) { 
    if (tx.isActive()) { 
     tx.rollback(); 
    } 
    logger.log(Level.SEVERE, null, e); 
} 
emB.close(); 
+0

我知道。但是,当我使用该方法时,会抛出OptimisticLockException。 – nashuald 2012-07-30 21:20:51

+0

向我们展示您的代码,完整的堆栈跟踪,并告诉我们在引发此异常的代码中的行。 – 2012-07-30 21:23:30

+0

我确实粘贴了代码。谢谢你的帮助。 – nashuald 2012-07-30 21:50:02