Hibernate triggering constraint violations using orphanRemoval

Some remarks:

  • Since you have a bi-directional association, you need to add a mappedBy attribute to declare the owning side of the association.
  • Also don’t forget that you need to manage both sides of the link when working with bi-directional associations and I suggest to use defensive methods for this (shown below).
  • And you must implement equals and hashCode on Contact.

So, in Account, modify the mapping like this:

@Entity
public class Account {
    @Id @GeneratedValue
    public Long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "account", orphanRemoval = true)
    public List<Contact> contacts = new ArrayList<Contact>();

    public void addToContacts(Contact contact) {
        this.contacts.add(contact);
        contact.setAccount(this);
    }

    public void removeFromContacts(Contact contact) {
        this.contacts.remove(contact);
        contact.setAccount(null);
    }

    // getters, setters
}

In Contact, the important part is that the @ManyToOne field should have the optional flag set to false:

@Entity
public class Contact {
    @Id @GeneratedValue
    public Long id;

    @ManyToOne(optional = false)
    public Account account;

    // getters, setters, equals, hashCode

}

With these modifications, the following just works:

Account account = new Account();
Contact contact = new Contact();

account.addToContact(contact);
em.persist(account);
em.flush();

assertNotNull(account.getId());
assertNotNull(account.getContacts().get(0).getId());
assertEquals(1, account.getContacts().size());

account.removeFromContact(contact);
em.merge(account);
em.flush();
assertEquals(0, account.getContacts().size());

And the orphaned Contact gets deleted, as expected. Tested with Hibernate 3.5.3-Final.

Leave a Comment