给定父实体
@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:Row被另一个事务更新或删除(或者unsaved-value映射不正确):
实际上,hibernate会发出两个sql更新:一个更改父属性,另一个更改子属性。你知道一种摆脱父母更新改变孩子的方法吗?更新导致乐观锁定效率低下和误报。请注意,child和parent都正确地将其状态保存在DB中。
Hibernate版本是3.5.1-Final
答案 0 :(得分: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());
}
如果这不能代表您的情况,请澄清。