I'm in the process of migrating a Hibernate 3 application to Hibernate 5.2. We have a couple of one-to-one unidirectional mappings with cascading (which we can't make bidirectional because the parent can't know anything about the other entities). The following (simplified example) worked fine in the latest Hibernate 3.x and latest Hibernate 4.x, but started running into ConstraintViolationExceptions in Hibernate 5.2:
public class Person {
@Id
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
@Column(name="person_id", length=32)
public String id;
/* other fields, getters and setters */
}
public class EnhancedPerson {
@Id
@Column(name="person_id", length=32)
@GeneratedValue(generator="foreign")
@GenericGenerator(
name="foreign",
strategy = "foreign",
parameters = { @Parameter(name="property", value="person") }
)
private String id;
@OneToOne(cascade = CascadeType.ALL, optional = false)
@PrimaryKeyJoinColumn
private Person person;
/* other fields, getters and setters */
}
As far as I could dig, when deleting an EnhancedPerson
, hibernate tries first to delete the Person
(because of the cascade), and of course this runs into a foreign key violation (because the EnhancedPerson
must reference a Person
, so it needs to be deleted first).
I tried simplifying the mapping to use JPA annotations as follows:
public class EnhancedPerson {
@Id
private String id;
@OneToOne(cascade = CascadeType.ALL, optional = false)
@MapsId
@JoinColumn("person_id")
private Person person;
/* other fields, getters and setters */
}
But the result has been the same. As far as I could dig, the usual recommendation is not to cascade from child to parent (e.g. this answer), also hibernate's documentation says Only the parent side of an association makes sense to cascade its entity state transitions to children.
I've also found this conversation that seems related, but the complaint is from Hibernate 5.3 to 5.4, and in my case it stopped working when going from 4.x to to 5.2. Also, I think the terminology is swapped there (what's called Child is the parent/owner of the relation, and what's called Parent is the child/has the foreign key) unless I'm the one with the confusion.
Any pointers how I could fix this, or if this works fine in more recent Hibernate versions? It might not normally make sense to cascade from child to parent, but in our case if the child is deleted, it makes no sense to keep the parent around (also, if the parent reference is modified through the child, those changes should also be persisted when persisting the child). Also, I wonder why this used to be supported and isn't anymore (I'm guessing a bug, but it could have been a purposeful breaking change).
CodePudding user response:
Reposting this as answer - Hibernate 5.2 is very old and lots of bugs have been fixed in the meantime in newer versions. As you found out by trying, the problem is gone in Hibernate 5.6.12.Final, so the solution is to update your dependencies ;)