I have a Parent entity with a Child entity in a ManyToOne relationship:
@Entity class Parent {
// ...
@ManyToOne((cascade = {CascadeType.ALL})
private Child child;
// ...
}
The Child has an unique field:
@Entity class Child {
// ...
@Column(unique = true)
private String name;
// ...
}
When I need a new Child, I ask the ChildDAO first:
Child child = childDao.findByName(name);
if(child == null) {
child = new Child(name);
}
Parent parent = new Parent();
parent.setChild(child);
The problem is, if I do like above twice (with the same name for the Child), and only persist the Parent at the end, I get a constraint exception. Which seems normal, since initially there was no child in the database with the specified name.
The problem is, I’m not sure what would be the best way to avoid this situation.
You are creating two non-persistent instances of Child with
new Child()twice then putting these in two different Parents. When you persist the Parent objects, each of the two new Child instances will be persisted/inserted via cascade, each with a different@Id. The unique constraint on the name then breaks. If you’re doing CascadeType.ALL, then every time you donew Child()you may be getting a separate persistent object.If you really wanted the two Child instances to be treated as a single persistent object with the same ID, you would need to persist it separately to associate with the persistence context/session. Subsequent calls to
childDao.findByNamewould then flush the insert and return the new Child you just created, so you won’t be doingnew Child()twice.