我使用Spring、Hibernate和JPA。(我会提到这是一个dropwizard应用程序,而不是springboot,尽管我不认为它应该有任何影响。
存储:MySql.
数据库中没有使用外键。
注意:
正如下面的一条评论所提到的,我完全同意将祖父母ID保存在子表中并不理想,遍历child -> parent -> grandparent是一个更好的做法。特别是对于这个问题,请考虑这是一个给定的情况(一种遗留代码,我现在不能改变…)
我有以下JPA实体:(姓名已更改)
祖父母:
@Entity
public class GrandParent {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@Column(name = "id", columnDefinition = "int unsigned not null")
private Long id;
//... some other fields... getters and setters
@OneToMany(mappedBy = "parent",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private Set<Parent> parents;
public void addParent(Parent parent) {
if (this.parents == null) {
this.parents = new HashSet<>();
}
this.parents.add(parent);
parent.setGrandParent(this);
}
public void removeParent(Parent parent) {
this.parents.remove(parent);
parent.setGrandParent(null);
}
}
父节点:
@Entity
public class Parent {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@Column(name = "id", columnDefinition = "int unsigned")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "grand_parent_id", referencedColumnName = "id", columnDefinition = "int unsigned")
private GrandParent grandParent;
@OneToMany(mappedBy = "parent",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private Set<Child> children;
// other fields, getters and setters
public void addChild(Child child) {
if (this.fields == null) {
this.fields = new HashSet<>();
}
this.children.add(child);
child.setParent(this);
}
public void removeChild(Child child) {
this.children.remove(child);
child.setParent(null);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Parent )) return false;
return id != null && id.equals(((Parent) o).getId());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
孩子:
@Entity
public class Child {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@Column(name = "id", columnDefinition = "int unsigned")
private Long id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "grand_parent_id", columnDefinition = "int unsigned")
private GrandParent grandParent;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id", columnDefinition = "int unsigned")
private Parent parent;
// other fields, getters and setters
}
我以以下方式创建了一个GrandParent instant(我只提到了相关的字段...):
Child child = Child.builder()
.someField("1")
.someOtherField(1)
.build();
Parent parent = Parent.builder()
.someField("1")
.someOtherField(1)
.build();
parent.addChild(child);
GrandParent grandParent = GrandParent.builder()
.someField("1")
.someOtherField(1)
.build();
grandParent.addParent(parent);
在“我的存储库”中,我使用以下命令保存祖父实体:
hibernateSession.save(grandParent);
事实上,所有行都成功存储,但child.grand_parent_id仍然为Null。
出了什么问题,如何解决?
为了更好的可见性,我添加了此更新(请参阅下面的@MauricioBuffon评论)
我试图通过编辑Parent
Entity中的addChild
方法来显式地在Child
中设置GrandParent
:
public void addChild(Child child) {
if (this.children == null) {
this.children = new HashSet<>();
}
this.children.add(child);
child.setParent(this);
//let's try...
child.setGrandParent(getGrandParent());
}
仍然是子项。grand_parent_id = Null。
所以问题依然存在:
出了什么问题,如何解决?
1条答案
按热度按时间rt4zxlrg1#
根本原因-我没有在子节点上显式设置grandParent。在这些实体之间建立一对一的单向关系,这是要走的路。
作者:MauricioBuffon