Java 更新子项时父项中未更新乐观锁定版本

Java 更新子项时父项中未更新乐观锁定版本,java,hibernate,jpa,orm,Java,Hibernate,Jpa,Orm,我有一位父母,他们有着无方向的一对多子女关系,并且通过@Version乐观锁定 当我编辑父项、添加子项或删除子项时,版本号会被碰撞,乐观锁定会起作用 我的问题是,当我编辑一个子版本本身时,父版本没有碰撞,因此锁定不起作用。有没有一种方法可以用JPA或hibernate的方式自动完成 所有对子项的修改都会经过父项,因此我可以通过每次调用方法时设置自己的版本/脏标志来检测它们,但这听起来不是一个正确的解决方案 我只希望在父级中有一个版本标志(它是聚合根)。在我的领域里,孩子们不能直接编辑,只能通过父

我有一位父母,他们有着无方向的一对多子女关系,并且通过
@Version
乐观锁定

当我编辑父项、添加子项或删除子项时,版本号会被碰撞,乐观锁定会起作用

我的问题是,当我编辑一个子版本本身时,父版本没有碰撞,因此锁定不起作用。有没有一种方法可以用JPA或hibernate的方式自动完成

所有对子项的修改都会经过父项,因此我可以通过每次调用方法时设置自己的版本/脏标志来检测它们,但这听起来不是一个正确的解决方案

我只希望在父级中有一个版本标志(它是聚合根)。在我的领域里,孩子们不能直接编辑,只能通过父母,所以这很有意义

使用
@PrePersist
@PreUpdate
不起作用(在子更新的情况下也不会触发)

使用
LockModeType.OPTIMISTIC\u FORCE\u INCREMENT
不起作用。下面是一个重现错误的代码示例:

//Main
var emFactory=buildFactory();//createEntityManagerFactory(“ORM”);
var em=emFactory.createEntityManager();
var transaction=em.getTransaction();
transaction.begin();
var parent=新父级(
1l,0,新建ArrayList(Arrays.asList(
新生儿(1公升,1公升,10岁),
新生儿(2公升、1公升、20公升),
新生儿(3公升、1公升、30公升)
))
);
em.persist(亲本);
commit();
//版本已更新
//更新父集合值=1,版本=1,其中id=1,版本=0
transaction.begin();
editParent();
commit();
//版本已更新
//插入子(父id、值、id)值(1、40、4)
//更新父集合值=1,版本=2,其中id=1,版本=1
//更新子集合parentId=1,其中id=4
transaction.begin();
父母。添加子女(新子女(4L、1L、40));
commit();
//更新父集合值=1,版本=3,其中id=1,版本=2
//更新子集合parentId=null,其中parentId=1,id=1
transaction.begin();
parent.removeFirstChild();
commit();
// !!! 版本没有更新!!!
//更新子集合parentId=1,value=21,其中id=2
transaction.begin();
parent.editFirstChild();
commit();
//母公司
导入javax.persistence.*;
导入java.util.List;
@实体
公共类父类{
@身份证
公共长id;
公共价值观;
@OneToMany(级联=级联类型.ALL)
@JoinColumn(name=“parentId”,referencedColumnName=“id”)
公开儿童名单;
@版本
公共int版本;
公共无效editParent(){
++价值观;
}
公共无效添加子对象(子对象){
this.children.add(child);
}
public void removeFirstChild(){
此.children.remove(0);
}
公共无效editFirstChild(){
++获取(0)值;
}
公共父项(长id、int值、列表子项){
this.id=id;
这个值=值;
这个。孩子=孩子;
}
}
//孩子
导入javax.persistence.Entity;
导入javax.persistence.Id;
@实体
公营儿童{
@身份证
长id;
长父ID;
int值;
公共子项(长id、长parentId、int值){
this.id=id;
this.parentId=parentId;
这个值=值;
}
}

请参阅。您需要手动执行此操作,因为对孩子的修改不是对家长的修改,所以一切都按设计进行。@Kayaman谢谢,我看过这篇文章,希望能有更简单的内容。答案中的解决方案解决了一个我们有双向关系的情况(@ManyToOne)在我们的例子中,子对象不知道其父对象,因此无法通过hibernate钩子(拦截器/集成器)通知它。在changedetection级别或使用这些挂钩时,可能仍有一些事情要做。