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