我正在尝试理解如何正确地注释类以使级联工作。
这是一个简单的父/子场景。
子:
@Entity
@Table(name = "testChild")
public class testChild implements Serializable {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "uuid", unique = true, nullable = false)
@JsonProperty
private String uuid;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="parent_uuid", nullable=false)
@Cascade(value={CascadeType.ALL})
@JsonIgnore
private testParent parent;
@Column(name = "name")
@JsonProperty
private String name;
public testChild (testParent parent, String name) {
this.uuid = UUID.randomUUID().toString();
this.name = name;
this.parent = parent;
}
public String getUuid() {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public testParent getParent () {
return this.parent;
}
public void setParent (testParent parent) {
this.parent = parent;
}
}
父:
@Entity
@Table(name = "testParent")
public class testParent implements Serializable {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "uuid", unique = true, nullable = false)
@JsonProperty
private String uuid; // This is the figure uuid:<number>
@Column(name = "name")
@JsonProperty
private String name;
@Column(name = "children")
@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", orphanRemoval=true, cascade = javax.persistence.CascadeType.ALL)
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
@JsonProperty
private List <testChild> children;
public testParent (String name) {
this.uuid = UUID.randomUUID().toString();
this.name = name;
this.children = new ArrayList<>();
}
public String getUuid() {
return this.uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public List <testChild> getChildren () {
return this.children;
}
public void setChildren (List <testChild> children) {
this.children = children;
}
public testChild addChild(String childname) {
testChild c = new testChild(this, childname);
this.children.add(c);
return c;
}
}
测试代码:
testParent p = new testParent("Dan");
sid = p.getUuid();
testChild c1 = p.addChild("Dan jr.");
testChild c2 = p.addChild("Dannielle");
session.save(p);
我的问题是它导致对(第一个)子节点的更新而不是插入:
DEBUG org.hibernate.SQL - insert into testParent (name, uuid) values (?, ?)
DEBUG org.hibernate.SQL - update testChild set name=?, parent_uuid=? where uuid=?
当然这会引发错误。 我在父类和子类中为Cascade尝试了很多组合。
唯一可行的是,如果我一直明确地“session.save(object)”。即 创建父 - 保存, 创建child1 - 保存, 创建child2 - 保存, 最后再次保存父母。
我真的很想知道如何告诉Hibernate从上到下简单地保存所有内容。
从这个网站和其他网站尝试了很多不同的建议,但似乎没有任何工作。
答案 0 :(得分:0)
您必须明确地将setter用于父级和子级。
以下是您需要做的事情:
testParent p = new testParent("Dan");
testChild c1 = new testChild("Dan");
testChild c2 = new testChild("Dannielle");
c1.setParent(p);
c2.setParent(p);
p.getChildren().add(c1);
p.getChildren().add(c2);
session.save(p);
你也可能混淆了实体级联。在OneToMany方面,即testParent
,您需要CascadeType.ALL
或包含CascadeType.PERSIST。您想说的是,无论何时您想要“插入”或“更新”或“删除”父母,也请对孩子们采取相同的行动。
父级的save
也应该将保存级联到其引用的子级。
答案 1 :(得分:0)
我有一个部分答案。它解决了这个问题,但我仍然有点困惑。 问题与使用生成的ID有关。我也试图手动设置它们,我认为它打破了父母和孩子之间的映射。
以下是一些有效的代码:
try {
testParent p = new testParent("Dan");
sid = p.getUuid();
testChild c1 = new testChild("Dan Jr.");
testChild c2 = new testChild("Danielle");
c1.setParent(p);
c2.setParent(p);
p.getChildren().add(c1);
p.getChildren().add(c2);
session.save(p);
tx.commit();
} catch(Exception e) {
tx.rollback();
log.error("Exception occured. "+e.getMessage());
assertTrue(false);
}
但它只在我做两件事情时才有效:
@GeneratedValue
和@GenericGenerator
注释。如果我不这样做,那么似乎setUuid在持久保存到数据库时不会更新uuid字段。该对象获取新的id,但只保存原始生成的ID。
我想知道这是否是最好的方法。