Java onetomany集合持有者的版本控制失败
给定父实体Java onetomany集合持有者的版本控制失败,java,hibernate,orm,versioning,optimistic-concurrency,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<Expendi
@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;
...
}
在一个事务中同时更新父事务和子事务时,会引发org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或者未保存的值映射不正确):
实际上,hibernate发布了两个sql更新:一个更改父属性,另一个更改子属性。你知道一种摆脱父更新更改子更新的方法吗?更新会导致乐观锁的效率低下和误报。请注意,子级和父级都正确地将其状态保存在DB中
Hibernate版本是3.5.1-Final
(…)实际上,hibernate发布了两个sql更新:一个更改父属性,另一个更改子属性
如果在一个事务中同时更新了父级和子级,这不是预期的结果吗
你知道一种摆脱父更新更改子更新的方法吗?更新会导致乐观锁的效率低下和误报
我不理解这个问题,也无法重现它。下面的测试方法(在事务内部运行)对我适用(由于我同时修改了父级和一个子级,所以它按预期生成了两个更新)
如果这不代表您的情况,请澄清。对不起,我有两个家长更新。一个在更新父级时,另一个在更新子级时。我将研究测试用例并将结果放在下面。我第一次尝试创建一个模拟中断版本控制的测试没有成功。我会做进一步的尝试,看看这是否真的是针对Spring的,或者是针对自然主义的。
@Entity
public class ExpenditurePeriod implements Serializable {
...
@ManyToOne
@JoinColumn(name="expenditure_id", nullable = false)
private Expenditure expenditure;
...
}
@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());
}