У меня есть отношение OneToMany, определенное следующим образом:
@Entity
Parent extends BaseEntity {
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE})
private List<Child> childList;
// ...
}
@Entity
Child extends BaseEntity {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "PARENT_ID")
private Parent parent;
// ...
}
Аннотация @Version определена в классе BaseEntity. Сущности преобразуются в DTO и изменяются клиентом. Теперь, когда клиент изменяет один из дочерних элементов, родительский и его дочерние элементы преобразуются обратно в сущности, а слияние выполняется путем выполнения em.merge(parent), версия ВСЕХ дочерних элементов увеличивается на единицу! Я ожидал, что увеличивается только версия измененного дочернего элемента. Сначала я подумал, что это из-за моего EntityCallbackListener, который перехватывает слияние с @PreUpdate. Но если я закомментирую метод обратного вызова, поля версий других дочерних элементов все равно будут увеличиваться. У кого-нибудь есть объяснение такому поведению?
Я использую OpenJPA 1.2.3.
Ладно, RTFM иногда помогает... :-/
Увеличение версии для всех дочерних элементов — это OpenJPA по умолчанию:
Этот диспетчер блокировок не выполняет никаких монопольных блокировок, а вместо этого обеспечивает согласованность чтения, проверяя, что версия всех заблокированных для чтения экземпляров остается неизменной в конце транзакции. Кроме того, блокировка записи вызовет приращение к версии в конце транзакции, даже если объект не был изменен иным образом. Это обеспечивает согласованность чтения с неблокирующим поведением.
Это настройка openjpa.LockManager по умолчанию в JPA.
Этот параметр можно переопределить с помощью диспетчера пессимистичных блокировок и его свойств:
Пессимистичный LockManager можно настроить для дополнительной проверки и увеличения версии диспетчера блокировки версий, описанного ниже, установив его свойства VersionCheckOnReadLock и VersionUpdateOnWriteLock.
Поэтому я настроил OpenJPA, чтобы не менять версию при обновлении:
<property name="openjpa.LockManager" value="pessimistic(VersionCheckOnReadLock=true,VersionUpdateOnWriteLock=false)"/>
Но это не работает. Поля версии всех дочерних элементов по-прежнему увеличиваются. Я что-то пропустил? Что мне нужно настроить, чтобы OpenJPA обновлял только поле версии измененных объектов?