Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PreUpdate not firing when adding to a collection [duplicate]

I have a JPA annotated class which contains a collection like so:

@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(){ ... }
}

What I'm seeing is that if I have a managed Employee entity and I add to it's collection of minions the preUpdate method is not getting invoked. A new row is added to the mapping table in the DB so I know the update is going through. If I change a property directly on the Employee, like name, then preUpdate fires as expected when the transaction is committed.

Is there a way to get PreUpdate to fire when a mapped collection is modified? Or is there some other technique or Hibernate specific annotation for detecting when this happens?

like image 506
Adam B Avatar asked Nov 23 '09 21:11

Adam B


2 Answers

@PreUpdate event is triggered just before database UPDATE operation is executed for the entity in question.

If you're not updating direct properties of Employee, there's no UPDATE to execute for its table and thus @PreUpdate listener is never called. You should have better luck using @PrePersist event which is triggered by "flush" rather than "update".

like image 186
ChssPly76 Avatar answered Sep 19 '22 10:09

ChssPly76


Maybe a this custom workaround works:

Create a subclass of ArrayList which identifies changes through ActionListener pattern

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);
    }

    .....
}
like image 34
rabolfazl Avatar answered Sep 20 '22 10:09

rabolfazl