当我尝试更新Parent并且Child是DTO时,我收到了EntityExistException。我该如何解决这个问题?我试过在Parent上调用merge,没有运气。我正在使用Spring数据jpa和hibernate。
@Entity
class Parent {
@Id
private int id;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "parent")
private Child child;
// getters and setters
}
@Entity
class Child {
@Id
private int id;
private String data;
@MapsId
@OneToOne
private Parent parent;
// getters and setters
}
在我的休息服务中,我正在做以下事情:
Child child = new Child(data); // data from request
Parent parent = parentRepositoryService.getParent(id);
parent.setChild(child);
parentRepositoryService.update(parent);
parentRepositoryService.class
class ParentRepositoryService {
public void update(Parent parent) {
parent.getChild().setParent(parent); // necessary to prevent Exception
parentRepository.save(parent);
}
}
我认为问题是Child对象已经在“parentRepositoryService.getParent(id)”调用的会话中。然后在会话外创建Child对象,导致旧的和新的Child对象之间不匹配。我宁愿不必从请求数据手动更新基于会话的Child对象,并且只想为子实体执行mysql“insert ... on duplicate key update”的等价物。
答案 0 :(得分:0)
我认为这是发生的事情:
您加载了一个包含子P
的父C1
。所以你现在有以下对象:
P -> C1
C1 -> P
箭头表示引用。
现在您创建一个新的子C2
并将其设置为P
的子项,并最终得到以下对象:
P -> C2
C1 -> P
C2 -> P
请注意C1
仍引用P
。当会话被刷新时,Hibernate使用子句中的引用来保持关系,并且你得到一个例外,因为P
被两个孩子引用。
为了修复它,取消将旧子项的引用设置为父项,您甚至可能希望将其删除。这应该发生在Parent
类中,就像
parent.getChild().setParent(parent)
应该是Parent.setChild