I'm using JPA2 and Hibernate implementation.
I've got simple mapping like this:
@Entity
class Topic {
@Id
@GeneratedValue(strategy = IDENTITY)
int id;
@OneToOne(cascade = ALL)
@JoinColumn(name = "id_poll")
private Poll poll;
}
@Entity
class Poll {
@Id
@GeneratedValue(strategy = IDENTITY)
int id;
}
Now, when I delete a Poll object which is also in Topic I get an error.
java.sql.SQLException: Integrity constraint violation FKCC42D924982D3F4B table: TOPICS in statement [delete from polls where id=?]
I understand that it is because I can't delete the Poll record if it has references in another table. How can I solve this problem? Do I have to manually set poll = null in a Topic table or is there a better solution?
This is expected behavior:
A common problem with bi-directional relationships is the application updates one side of the relationship, but the other side does not get updated, and becomes out of sync. In JPA, as in Java in general it is the responsibility of the application, or the object model to maintain relationships.
Source: Object corruption, one side of the relationship is not updated after updating the other side
The correct place to handle this is in a @PreRemove callback:
@Entity
class Poll {
...
@PreRemove
private void preRemove() {
Poll poll = topic.getPoll();
topic.setPoll( null );
}
}
See also: Have JPA/Hibernate to replicate the “ON DELETE SET NULL” functionality
I was not able to find a solution by now, so before I delete a Poll object I always get a Topic object which contains given Pool and set it to null.
Topic topic = entityManager.find( Topic.class, 1 );
Poll poll = topic.getPoll();
topic.setPoll( null );
entityManager.remove( poll );
And it works correctly.
It looks like the @OneToOne annotation in JPA 2 contains an orphanRemoval flag, you could try setting that and see if it removes it gracefully.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With