2010-09-10 46 views
2

我的问题是类似JPA最佳实践问题 - 更新一个字段只

Updating one field in JPA entity

基本上我有其中有一些基本的字段(enumStringDateTime),它有两个其他领域的实体美孚。其中之一是OneToOne,另一个是使用集合实现的OneToMany。

我有两个线程它们在不同的时间运行,并查找使用findById类型的方法在辛格尔顿的EntityManager包装类相同的实体(我没有写这一点;)

我想什么,以避免是以下情况:

线程1查找一个Foo其中具有1的ID和它得到在该时间点的基准,以与富富的状态。

线程2查找一个Foo其中具有1的ID,并得到一个裁判的Foo与相同的状态的线程1

线程1改变上富字符串字段中,并用合并 线程持续,2更改foo上的Enum字段的值并将其保留为合并结果

上次操作导致更改线程1被替换为线程2得到的旧字段的状态,因为合并正在更新所有内容(除外OneToOne和OneToMany,因为它们的CascadeType是Persist和Remove)。

我所寻找的是建议,以最佳实践方法将防止这种状态重挫当一个人只需要更新以这种方式具体领域的东西。

虽然我有,我认为是在我的帖子顶部的链接中提到的,但它改变了使用现在使用的通用save(Object o)的东西,它将合并到特定于这种情况下,从实体ID键入的特定字段上执行UPDATE。有没有更好的办法?我目前的持久性提供者是EclipseLink。

TIA

-NBW

+0

你能发表一些代码吗? – 2010-09-11 02:45:55

+0

请参阅[这里]的答案(http://stackoverflow.com/questions/3476613/updating-one-field-in-jpa-entity/18875850#18875850)查看JPA 2.1支持部分实体更新 – 2013-09-18 15:06:42

回答

0

首先,你可以利用该处理这类情况的交易。如果性能不是问题,请使用悲观锁定并解决问题 - 第二个线程将等待第一个线程更新值。

但我同意这个用例应该有更简单的东西。您可以使用普通JDBC并撰写更新查询。

3

你应该用乐观锁(@版本)在JPA。这会导致第二个客户端的事务失败。

另外的EclipseLink只会更新变化的领域,所以如果你读这两个对象进入交易/持久化上下文,他们只会更新他们改变了场。让它恢复更改的唯一方法是,如果在读取对象后对其进行序列化或分离,然后将其合并回新的持久性上下文中。 (请注意,merge()仅适用于分离的对象,因为它们已经被管理,所以不应该用于管理对象)。

1

Thread1引用Foo的分离实例,并且thread2引用Foo的diff实例,乐观锁定(@Version)将不起作用,因为当您尝试第二次保存分离的实例时,它将引发异常,Best方法来解决你的问题是你合并之前要做到这一点,每次你脱离实体

SOL1: //加载富每次你改变 富= em.find(foodId,让Foo.class); //foo.set ..使变化 em.merge(富)

SOL2: // FOO指的是分离的实体 em.refresh(FOO); //foo.set .. make change em.merge(foo)