The problem is somehow explained in the page about ElementCollection
of the JPA wikibook:
Primary keys in CollectionTable
The JPA 2.0 specification does not
provide a way to define theId
in the
Embeddable
. However, to delete or
update a element of the
ElementCollection
mapping, some unique
key is normally required. Otherwise,
on every update the JPA provider would
need to delete everything from the
CollectionTable
for theEntity
, and
then insert the values back. So, the
JPA provider will most likely assume
that the combination of all of the
fields in theEmbeddable
are unique,
in combination with the foreign key
(JoinColunm
(s)). This however could be
inefficient, or just not feasible if
theEmbeddable
is big, or complex.
And this is exactly (the part in bold) what happens here (Hibernate doesn’t generate a primary key for the collection table and has no way to detect what element of the collection changed and will delete the old content from the table to insert the new content).
However, if you define an @OrderColumn
(to specify a column used to maintain the persistent order of a list – which would make sense since you’re using a List
), Hibernate will create a primary key (made of the order column and the join column) and will be able to update the collection table without deleting the whole content.
Something like this (if you want to use the default column name):
@Entity
public class Person {
...
@ElementCollection
@CollectionTable(name = "PERSON_LOCATIONS", joinColumns = @JoinColumn(name = "PERSON_ID"))
@OrderColumn
private List<Location> locations;
...
}
References
- JPA 2.0 Specification
- Section 11.1.12 “ElementCollection Annotation”
- Section 11.1.39 “OrderColumn Annotation”
- JPA Wikibook