1

给定的父实体

@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;
...
}

和孩子一

@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

4

1 回答 1

0

(...) 实际上,hibernate 发布了两个 sql 更新:一个更改父属性,另一个更改子属性。

如果您在一次事务中同时更新了父子节点,这不是预期的结果吗?

你知道摆脱父母更新改变孩子的方法吗?更新导致乐观锁效率低下和误报。

我不明白这个问题,也无法重现它。以下测试方法(在事务中运行)对我有用(并且它按预期生成两个更新,因为我修改了父项和一个子项)。

@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());
}

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

于 2010-04-28T07:04:34.853 回答