2009-11-23 19 views
11

Mam WZP uwagami klasy, która zawiera zbiór tak:PreUpdate nie wypalanie podczas dodawania do kolekcji

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

co widzę jest to, że jeśli mam zarządzanego podmiotu pracownika i dodaję do jego kolekcja sługusów metoda preUpdate nie jest wywoływana. Nowy wiersz jest dodawany do tabeli odwzorowań w DB, więc wiem, że aktualizacja przechodzi. Jeśli zmienię właściwość bezpośrednio na pracownika, np. Nazwę, to preUpdate wystrzeli zgodnie z oczekiwaniami, gdy transakcja zostanie zatwierdzona.

Czy istnieje sposób na uruchomienie PreUpdate, gdy zmapowana kolekcja zostanie zmodyfikowana? Czy jest tam inna technika lub adnotacja Hibernate do wykrywania, kiedy to się dzieje?

Odpowiedz

5

@PreUpdate Zdarzenie jest wywoływane tuż przed wykonaniem database UPDATE operation dla danego obiektu.

Jeśli nie aktualizujesz bezpośrednich właściwości Employee, nie ma potrzeby wykonywania UPDATE dla jego tabeli, przez co detektor @PreUpdate nigdy nie jest wywoływany. Powinieneś mieć więcej szczęścia używając zdarzenia @PrePersist, które jest wyzwalane przez "flush" zamiast "update".

+1

Masz rację. PrePersist również nie pomaga, ponieważ jest uruchamiany przy pomocy INSERT iw tym przypadku kolekcja jest modyfikowana po tym, jak obiekt został już utrwalony. Domyślam się, że moje pytanie naprawdę pyta, czy istnieją techniki, które działają podobnie do PreUpdate, aby wykryć, kiedy zmapowana kolekcja jest modyfikowana. –

+1

Nie jestem pewien, co masz na myśli przez "wyrzucony na INSERT". Czy nie nazywasz "entityManager.persist (employee)", aby zapisać swoją kolekcję? Jeśli nie jesteś (np. Polegasz na flush _only_), będziesz musiał skonfigurować własnego słuchacza dla jednego (lub więcej) zdarzeń "flush"/"auto-flush"/"flush-entity" (http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html#d0e500). Lub, dla rozwiązania specyficznego dla Hibernate, napisz własny przechwytujący (http://docs.jboss.org/hibernate/stable/core/reference/en/html/events.html#objectstate-interceptors) - onFlushDirty() jest zawsze nazywa – ChssPly76

2

Może ten zwyczaj obejście działa:

utworzyć podklasę ArrayList, który identyfikuje zmiany poprzez ActionListener wzór

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

    ..... 
} 
0

Oto moja realizacja dla operatora hibernacji:

http://pastebin.com/8cPB96bZ

Ogólnie wystarczy zaznaczyć metody, które powinny zostać wywołane w przypadku brudnej kolekcji za pomocą @PreCollectionChan adnotacja ge.

Powiązane problemy