Версия всех дочерних элементов увеличивается в OneToMany при объединении родительского объекта

У меня есть отношение 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 обновлял только поле версии измененных объектов?


person mwalter    schedule 03.08.2011    source источник


Ответы (1)


Проблема заключалась в неправильной реализации equals() и hashcode(), поэтому EntityManager предположил, что все объекты в списке были изменены.

person mwalter    schedule 02.09.2011