Java JPA版本实体合并
我知道关于这个问题已经有一些问题了,但我认为这个问题是不同的 假设我有一门课:Java JPA版本实体合并,java,jpa,h2,Java,Jpa,H2,我知道关于这个问题已经有一些问题了,但我认为这个问题是不同的 假设我有一门课: @Entity public class foo{ @Id @GeneratedValue private long id; @Version private long version; private String description; ... } 我创建了一些对象,并使用JPA add()将它们持久化到数据库中 稍后,我使用jpaall()从存储库获取所有信息; 从该列表中,
@Entity
public class foo{
@Id
@GeneratedValue
private long id;
@Version
private long version;
private String description;
...
}
我创建了一些对象,并使用JPA add()将它们持久化到数据库中
稍后,我使用jpaall()从存储库获取所有信息;
从该列表中,我选择一个对象并更改描述
然后我想使用jpamerge()更新存储库中的该对象(请参见代码)
这里的问题是,在我第一次尝试更改描述时它就起作用了(版本值现在是2)。
第二次,一个OptimisticLockException被提出,表示该对象同时被更改
我在嵌入式模式下使用H2有DB
合并代码:
//First: persist is tried, if the object already exists, an exception is raised and then this code is executed
try {
tx = em.getTransaction();
tx.begin();
entity = em.merge(entity);
tx.commit();
} catch (PersistenceException pex) {
//Do stuff
}
哪里会出什么问题
多谢各位
编辑(更多代码)
//foob是通过使用jpaall()从数据库获取所有对象获得的,然后从该列表中选择一个对象
b、 changeDescription(“新事物!”)
//调用更新方法(合并代码已发布)当抛出OptimisticLockException
时,这篇文章可以很好地解释
此外,仅供将来参考,您可以让JPA在更新实体时避免对实体进行这种内存验证,但要在事务结束时使用EntityManager
上的detach
方法在DB端进行更改:
em.detach(employee);
我假设您正在更改来自不同客户端或不同线程的列表中的元素。这就是导致出现
OptimisticLockException
的原因
一个线程,在它自己的EntityManager
中,读取Foo
对象,并在读取时获取@Version
// select and update AnyEntity
EntityManager em1 = emf.createEntityManager();
EntityTransaction tx1 = em1.getTransaction();
tx1.begin();
AnyEntity firstEntity = em1.createQuery("select a from AnyEntity a", AnyEntity.class).getSingleResult();
firstEntity.setName("name1");
em1.merge(firstEntity);
在第一个客户端将其更改提交到数据库之前,另一个客户端同时读取并更新Foo
对象:
// select and update AnyEntity from a different EntityManager from a different thread or client
EntityManager em2 = emf.createEntityManager();
EntityTransaction tx2 = em2.getTransaction();
tx2.begin();
AnyEntity secondEntity = em2.createQuery("select a from AnyEntity a", AnyEntity.class).getSingleResult();
secondEntity.setName("name2");
em2.merge(secondEntity);
// commit first change while second change still pending
tx1.commit();
em1.close();
现在,第一个客户端将其更改提交到数据库:
// select and update AnyEntity from a different EntityManager from a different thread or client
EntityManager em2 = emf.createEntityManager();
EntityTransaction tx2 = em2.getTransaction();
tx2.begin();
AnyEntity secondEntity = em2.createQuery("select a from AnyEntity a", AnyEntity.class).getSingleResult();
secondEntity.setName("name2");
em2.merge(secondEntity);
// commit first change while second change still pending
tx1.commit();
em1.close();
当第二个客户端更新其更改时,它将获得一个OptimisticLockException
:
// OptimisticLockException thrown here means that a change happened while AnyEntity was still "checked out"
try {
tx2.commit();
em2.close();
} catch (RollbackException ex ) {
Throwable cause = ex.getCause();
if (cause != null && cause instanceof OptimisticLockException) {
System.out.println("Someone already changed AnyEntity.");
} else {
throw ex;
}
}
参考:是否正确初始化版本字段 如果不是,则不应使用
null
,请尝试向其添加默认值:
@Version
private Long version = 0L;
您是否尝试过使用em.persist而不是merge?合并方法在更新后继续跟踪对象。根据您的配置,更新可能已经进入数据库。请发布更多代码。相关的是如何加载和修改实体,以及如何调用发布的代码。@AlanHay我用一些表示我的situation@fhofmann我编辑了回答你问题的“合并代码”。