I have bidirectional mapping between Family and Person:
@Entity class Family {
@OneToMany(mappedBy = "family", ...)
Set<Person> persons;
...
}
@Entity class Person {
@ManyToOne
Family family;
...
}
My problem is that I can concurrently add and/or remove elements from the collection, which it breaks atomicity in the updates, as adding a new person creates INSERT INTO Person ... statement that does not collide with the other insert. @Version field does not help, since I am not updating the Family entity as row in the table, just logically.
What should I do to enable only atomic updates of the collection? I have tried loading Family with LockMode.PESSIMISTIC_WRITE, which can synchronize the updates on the Family itself, but that does not allow second-level caching for the read of Family. I would prefer optimistic transactions with kind of predicate constraint in the DB.
You can use OPTIMISTIC_FORCE_INCREMENT:
entityManager.lock(family, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
This way version will be checked and incremented in the corresponding Family entity instance.
EDIT
Since you are using L2 cache, and for some reason (bug, design decision, or just a missing feature) Hibernate does not update the version in the L2 cache after the force increment, you will have to actually load the entity with this lock for everything to work properly:
entityManager.find(Family.class, id, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
However, now you will have to take care to be consistent and to load the Family entities this way always prior to updating them (to avoid working with stale version values because L2 cache is not in sync with the database).
To overcome this, you could add an artificial column to the Family entity, like lastUpdateTime or something, and update the Family instance without using any explicit lock. Then the regular version check would occur and everything would be synchronized with the L2 cache.
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