PreUpdate не стрелять при добавлении в коллекцию

У меня есть аннотированный класс JPA, который содержит такую ​​коллекцию:

@Entity
public class Employee {
    @Id
    private int id; 
    @Basic
    private String name;    
    @OneToMany
    @JoinTable(name = "ORG", joinColumns = @JoinColumn(name="MINION"),
        inverseJoinColumns = @JoinColumn(name="EMP"))
    private List<Employee> minions = new ArrayList<Employee>();

    @PreUpdate
    public void preUpdate(){ ... }
}

Я вижу, что если у меня есть управляемая сущность Employee, и я добавляю к ней коллекцию миньонов, метод preUpdate не будет вызван. Новая строка добавляется в таблицу сопоставления в БД, поэтому я знаю, что обновление прошло. Если я изменяю свойство непосредственно на Работника, например имя, тогда preUpdate срабатывает, как ожидалось, когда транзакция совершена.

Есть ли способ заставить PreUpdate срабатывать при изменении сопоставленной коллекции? Или есть какой-то другой метод или конкретная аннотация Hibernate для обнаружения, когда это происходит?

Ответ 1

@PreUpdate событие запускается непосредственно перед тем, как база данных UPDATE выполняется для рассматриваемого объекта.

Если вы не обновляете прямые свойства Employee, для его таблицы нет UPDATE, и поэтому @PreUpdate прослушиватель никогда не вызывается. Вам лучше повезти с помощью события @PrePersist, которое запускается с помощью "flush", а не "update".

Ответ 2

Возможно, это обычное обходное решение работает:

Создайте подкласс ArrayList, который идентифицирует изменения с помощью шаблона ActionListener

public class Employee {
    ....

    private List<Employee> minions = createChangeNotifierList();

    private List<Employee> createChangeNotifierList() {
        ChangeNotifierList<Employee> l = new ChangeNotifierList<Employee>();
        l.setActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                preUpdate();
            }
        });
        return l;
    }

    public void setMinions(List<Employee> l) {
        if (!(l instanceof ChangeNotifierList)) {
            l = createChangeNotifierList();
            preUpdate();
        }
        this.minions = l;
    }

    public void preUpdate(){ ... }
}


public class ChangeNotifierList<T> extends ArrayList<T> {

    private ActionListener actionListener;

    public ChangeNotifierList() {
    }

    public ChangeNotifierList(List<T> list) {
        super.addAll(list);
    }

    public void setActionListener(ActionListener actionListener) {
        this.actionListener = actionListener;
    }

    public boolean add(T e) {
        boolean b = super.add(e);
        if (b) {
            notifyChange();
        }
        return b;
}

    private void notifyChange() {
        actionListener.actionPerformed(null);
    }

    .....
}

Ответ 3

Вот моя реализация для поставщика Hibernate:

http://pastebin.com/8cPB96bZ

Обычно вы просто отмечаете методы, которые должны быть вызваны в случае грязной коллекции с аннотацией @PreCollectionChange.