java - onetomany 集合持有者的版本控制失败

标签 java hibernate orm versioning optimistic-concurrency

给定父实体

@Entity
public class Expenditure implements Serializable {
...
    @OneToMany(mappedBy = "expenditure", cascade = CascadeType.ALL, orphanRemoval = true)
    @OrderBy()
    private List<ExpenditurePeriod> periods = new ArrayList<ExpenditurePeriod>();

    @Version
    private Integer version = 0;
...
}

和 child 一

@Entity
public class ExpenditurePeriod implements Serializable {
...
    @ManyToOne
    @JoinColumn(name="expenditure_id", nullable = false)
    private Expenditure expenditure;
...
}

在一个事务中更新父级和子级时,会抛出 org.hibernate.StaleObjectStateException:行已被另一事务更新或删除(或未保存值映射不正确):

事实上,hibernate 发出两个 sql 更新:一个更改父属性,另一个更改子属性。您知道一种摆脱父更新更改子的方法吗?更新会导致乐观锁效率低下和误报。请注意,子级和父级都正确地将其状态保存在数据库中。

Hibernate 版本为 3.5.1-Final

最佳答案

(...) Indeed, hibernate issues two sql updates: one changing parent properties and another changing child properties.

如果您在一个事务中更新了父级和子级,这不是预期的结果吗?

Do you know a way to get rid of parent update changing child? The update results both in inefficiency and false positive for optimistic lock.

我不明白这个问题,也无法重现它。以下测试方法(在事务内运行)适合我(由于我修改了父项和一个子项,它按预期生成了两个更新)。

@Test
public void testUpdate() {
    Expenditure expenditure = new Expenditure();
    ExpenditurePeriod expenditurePeriod1 = new ExpenditurePeriod();
    ExpenditurePeriod expenditurePeriod2 = new ExpenditurePeriod();

    expenditure.getPeriods().add(expenditurePeriod1);
    expenditure.getPeriods().add(expenditurePeriod2);
    expenditurePeriod1.setExpenditure(expenditure);
    expenditurePeriod2.setExpenditure(expenditure);

    em.persist(expenditure);
    em.flush();

    assertNotNull(expenditure.getId());
    assertNotNull(expenditurePeriod1.getId());
    assertNotNull(expenditurePeriod2.getId());
    assertEquals(Integer.valueOf(0), expenditure.getVersion());
    assertEquals(Integer.valueOf(0), expenditurePeriod1.getVersion());
    assertEquals(Integer.valueOf(0), expenditurePeriod2.getVersion());

    expenditure.setProperty("a");
    expenditurePeriod1.setProperty("b");

    em.merge(expenditure);
    em.flush();

    assertEquals(Integer.valueOf(1), expenditure.getVersion());
    assertEquals(Integer.valueOf(1), expenditurePeriod1.getVersion());
    assertEquals(Integer.valueOf(0), expenditurePeriod2.getVersion());
}

如果这不能代表您的情况,请澄清。

关于java - onetomany 集合持有者的版本控制失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2721621/

相关文章:

java - 向 DTO 对象添加行为

ArrayList 上的 java.util.ConcurrentModificationException

java - 在 Java 中抛出 ArithmeticException() 的所有无效操作的列表?

hibernate - org.hibernate.type.SerializationException : could not deserialize

java - 在 Hibernate 中存储坐标 (x,y) 的首选方式是什么?

mysql - 混合数据库关系?

java - JComponent 内容 Pane

java - 在 spring 项目中使用 hibernate 工具

java - 从两个不同的数据库中检索相同 DTO 的信息

database - 如何设计一个与其自身具有多对多关系的表?