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.