Spring数据和双向关系的持久性上下文问题
这个问题在编写测试时出现,但可能也适用于应用程序代码,这给我留下了一些问题 (问题就在底部) 情况摘要:Spring数据和双向关系的持久性上下文问题,spring,hibernate,jpa,spring-data,Spring,Hibernate,Jpa,Spring Data,这个问题在编写测试时出现,但可能也适用于应用程序代码,这给我留下了一些问题 (问题就在底部) 情况摘要: 我正在编写DataJpaTests测试,以测试由一些crudepositories支持的服务层对象。 最初,我使用一些数据为存储库添加种子,然后进行服务调用 最后,我查询存储库以断言状态 我在父母和孩子之间有双向的一对多关系(ren) 子对象将其父对象作为自然Id的一部分 在我的断言中,parent.getChildren().contains(child)失败为false,但它应该为
- 我正在编写
测试,以测试由一些DataJpaTests
支持的服务层对象。crudepositories
- 最初,我使用一些数据为存储库添加种子,然后进行服务调用
- 最后,我查询存储库以断言状态
- 我在父母和孩子之间有双向的一对多关系(ren)
- 子对象将其父对象作为自然Id的一部分
- 在我的断言中,
失败为parent.getChildren().contains(child)
,但它应该为truefalse
@测试
公开无效测试(){
//种子
Parent=Parent.builder()
.电邮(“a@b.cbuild();
Child=Child.builder()
.电邮(“x@y.zbuild();
parent.addChild(child);
parentRepository.save(父级);
// ----
//忽略不相关的服务代码
// ----
//断言
parent=parentRepository.findById(parent.getId()).get();
assertTrue(parent.getChildren().contains(child));//失败
}
这让我进行了调试和调查。结果表明,父对象的子对象
集与之前的持久集
完全相同。那时我学到了更多关于持久性上下文的知识,尽管这些知识仍然很肤浅
如果我执行以下任一操作,则测试通过:
parentRepository.save(parent)
EntityManager
并调用refresh(父项)
或flush()、clear()
组合addChild
中的操作,以便在插入父对象的子对象集中之前为子对象指定父对象Child
的hashcode中有parent
,并且当最初插入到父对象的子对象集中时,没有指定父对象,因此hashcode是不同的
为供参考,各实体:
@实体
@Getter@Setter@Builder
@noargsconstuctor@allargsconstuctor
公共类父类{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@归化
私人字符串电子邮件;
@OneToMany(mappedBy=“parent”,cascade=CascadeType.ALL,orphan=true)
@Builder.Default
private Set children=new HashSet();
公共无效添加子项(最终子项){
getChildren().add(child);
child.setParent(this);
}
public void removeChild(最终子级){
getChildren().remove(子对象);
setParent(null);
}
@凌驾
公共布尔等于(最终对象o){
if(this==o){
返回true;
}
如果(o==null | | getClass()!=o.getClass()){
返回false;
}
最终父项=(父项)o;
返回email.equals(parent.email);
}
@凌驾
公共int hashCode(){
返回Objects.hash(电子邮件);
}
}
@实体
@Getter@Setter@Builder
@noargsconstuctor@allargsconstuctor
公营儿童{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@归化
私人字符串电子邮件;
@多通(可选=假)
@JoinColumn(name=“parent\u identifier”)
@归化
私人家长;
@凌驾
公共布尔等于(最终对象o){
if(this==o){
返回true;
}
如果(o==null | | getClass()!=o.getClass()){
返回false;
}
最终子女=(子女)o;
返回email.equals(child.email)&&
parent.equals(child.parent);
}
@凌驾
公共int hashCode(){
返回Objects.hash(电子邮件、父级);
}
}
EntityManager
手动执行,PersistentSet
什么时候会被刷新/重新刷新Parent::addChild
中反转操作顺序是否有任何副作用