@Entity
public class Person {
@ElementCollection
@CollectionTable(name = "PERSON_LOCATIONS", joinColumns = @JoinColumn(name = "PERSON_ID"))
private List<Location> locations;
[...]
}
@Embeddable
public class Location {
[...]
}
Given the following class structure, when I try to add a new location to the list of Person's Locations, it always results in the following SQL queries:
DELETE FROM PERSON_LOCATIONS WHERE PERSON_ID = :idOfPerson
And
A lotsa' inserts into the PERSON_LOCATIONS table
Hibernate (3.5.x / JPA 2) deletes all associated records for the given Person and re-inserts all previous records, plus the new one.
I had the idea that the equals/hashcode method on Location would solve the problem, but it didn't change anything.
Any hints are appreciated!
The problem is somehow explained in the page about
ElementCollection
of the JPA wikibook: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 aList
), 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):
References
In addition to Pascal's answer, you have to also set at least one column as NOT NULL:
This requirement is documented in AbstractPersistentCollection:
We discovered that entities we were defining as our ElementCollection types did not have an
equals
orhashcode
method defined and had nullable fields. We provided those (via @lombok for what it's worth) on the entity type and it allowed hibernate (v 5.2.14) to identify that the collection was or was not dirty.Additionally, this error manifested for us because we were within a service method that was marked with the annotation
@Transaction(readonly = true)
. Since hibernate would attempt to clear the related element collection and insert it all over again, the transaction would fail when being flushed and things were breaking with this very difficult to trace message:HHH000346: Error during managed flush [Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1]
Here is an example of our entity model that had the error
Changing it to this
Fixed our issue. Good luck.