添加到集合时不触发 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 时不维护文件夹结构 [重复]

循环记录集并添加到字典/集合:项目键存在

iOS开发 在异步线程里面添加定时器,或者perform afterDelay时不响应的问题

python-集合