I'm trying to understand how to properly annotate classes to get cascading to work.
Here is a simple parent/children scenario.
Child:
@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;
}
}
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;
}
}
And the test code:
testParent p = new testParent("Dan");
sid = p.getUuid();
testChild c1 = p.addChild("Dan jr.");
testChild c2 = p.addChild("Dannielle");
session.save(p);
My problem is that it's resulting in an update to the (first) child instead of an insert:
DEBUG org.hibernate.SQL - insert into testParent (name, uuid) values (?, ?)
DEBUG org.hibernate.SQL - update testChild set name=?, parent_uuid=? where uuid=?
Of course this throws an error. I have tried quite a few combinations for Cascade in both the parent and child classes.
The only thing that does work is if I explicitly "session.save(object)" all the time. i.e. Create the parent - save, create child1 - save, create child2 - save, finally save the parent again.
I'd really like to know how to tell Hibernate to simply save everything from the top down.
Tried a lot of different suggestions from this site and others, but nothing seems to be working.