添加到集合时不触发 PreUpdate [重复]
Posted
技术标签:
【中文标题】添加到集合时不触发 PreUpdate [重复]【英文标题】:PreUpdate not firing when adding to a collection [duplicate] 【发布时间】:2009-11-23 21:59:41 【问题描述】:我有一个 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 实体并且我添加到它的 minions 集合中,则不会调用 preUpdate
方法。数据库中的映射表中添加了一个新行,因此我知道更新正在进行中。如果我直接更改 Employee 上的属性,例如姓名,那么preUpdate
会在事务提交时按预期触发。
有没有办法让 PreUpdate 在映射集合被修改时触发?或者是否有其他技术或 Hibernate 特定注释来检测何时发生这种情况?
【问题讨论】:
使用@Version - 见***.com/a/17073342/178526 【参考方案1】:@PreUpdate
事件在为相关实体执行 database UPDATE operation 之前触发。
如果您不更新Employee
的直接属性,则没有要为其表执行的UPDATE
,因此永远不会调用@PreUpdate
侦听器。使用由“flush”而不是“update”触发的@PrePersist
事件应该会有更好的运气。
【讨论】:
你是对的。 PrePersist 也无济于事,因为它是在 INSERT 上触发的,在这种情况下,在实体已经持久化之后会修改集合。我想我的问题实际上是在问是否有类似于 PreUpdate 的技术来检测映射集合何时被修改。 我不确定您所说的“在插入时触发”是什么意思。你不是打电话给entityManager.persist(employee)
来保存你的收藏吗?如果你不是(例如你依赖于flush only)你将不得不为一个(或多个)“flush”/“auto-flush”/ “刷新实体”事件 (docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/…)。或者,对于特定于 Hibernate 的解决方案,编写自己的拦截器 (docs.jboss.org/hibernate/stable/core/reference/en/html/…) - 始终调用 onFlushDirty()【参考方案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 注释标记在脏集合的情况下应调用的方法。
【讨论】:
包含导入语句总是一个好主意,因此在任何情况下都可以确定确切需要哪个导入。在这种情况下,我知道您从哪里获取 ReflectionUtils。现在,我认为许多第三方库都有一个名为ReflectionUtils
的类以上是关于添加到集合时不触发 PreUpdate [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Symfony2:PrePersist/PreUpdate 生命周期事件未触发
hibernate/JPA 中的 @PreUpdate 和 @Prepersist(使用会话)
iexpress 在扩展到 temp 时不维护文件夹结构 [重复]