16

I am having trouble working out how to do a bulk delete of a Person object using JPA, when the Person objects contain data stored using an @ElementCollection. Any ideas on how to do this would be much appreciated.

@Entity
@Table(name="at_person")
public class Person implements Comparable<Person> {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id")
    private long id = 0;

    @Column(name="name", nullable = true, length = 128)
    private String name = "";

    @ElementCollection
    @Column(name = "email")
    @CollectionTable(name = "person_email", joinColumns = @JoinColumn(name = "person_id"))
    private Set<String> email = new HashSet<String>();
}

What I am doing at the moment is this, and it fails with a foreign key constraint error:

Query query=em.createQuery("DELETE FROM Person");

Caused by: java.sql.SQLException: integrity constraint violation: foreign key no action; FKCEC6E942485388AB table: PERSON_EMAIL

If it can be a pure JPA annotation rather than a Hibernate annotation that would be a bonus!

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
corydoras
  • 7,130
  • 12
  • 55
  • 58

1 Answers1

29

I'll let you interpret the part of the JPA 2.0 specification that mentions that a bulk delete operation is not cascaded:

4.10 Bulk Update and Delete Operations

...

A delete operation only applies to entities of the specified class and its subclasses. It does not cascade to related entities.

And the fact is that Hibernate won't cascade a delete to a collection table either. This has been reported in HHH-5529 and the suggested approaches are:

You could also (a) clean up the collection table yourself or (b) use cascading foreign keys in the schema.

In other words, (a) use native SQL or (b) use a cascade delete constraint at the database level - and you'll have to add it manually, I don't think you can use @OnDelete with the @ElementCollection annotation (same story as HHH-4301 IMO).

Archie
  • 4,959
  • 1
  • 30
  • 36
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 11
    Hmm, I am shocked that JPA would have such a glaring bug. This means if you are trying to use JPA to clear out data in a very large table you have to iterate over each object one by one, or hope manually turn on cascading delete! Maybe I should take another look back at JDO – corydoras Oct 11 '10 at 03:30
  • @corydoras I mentioned the options. Your call. – Pascal Thivent Oct 11 '10 at 03:46
  • 1
    Yes thanks for the info! Life is too short to spend time fiddling around with workarounds for something that should be simple (: For now we have code iterate over each object and manually delete them. – corydoras Oct 13 '10 at 22:22
  • link seems broken for 5529... but should be available at https://hibernate.atlassian.net/browse/HHH-5529 – arcuri82 Oct 11 '16 at 13:31
  • anyway, it might be part of the specs, but it looks like a huge limitation :( if not going to be fixed in next specs of JPA, it would had been great if getting some non-standard non-JPA command in Hibernate... but that HHH-5529 seems opened since 2010... I guess also that a possible workaround would be to get completely rid off of ElementCollection, and wrap the base elements in their own Entity (although I guess it would not be particularly efficient...) – arcuri82 Oct 11 '16 at 13:37
  • CriteriaDelete in Spec 2.1 does not mention cascade. Is cascade for bulk delete supported in JPA 2.1? – eastwater Jan 09 '18 at 01:49