2009-11-23 10 views
11

tengo una clase anotada APP que contiene una colección de este modo:PreUpdate no disparar cuando se añade a una colección

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

Lo que estoy viendo es que si tengo una entidad Employee administrado y agrego que es colección de minions El método preUpdate no se invoca. Se agrega una nueva fila a la tabla de asignación en el DB, así sé que la actualización está en proceso. Si cambio una propiedad directamente en el Empleado, como el nombre, entonces preUpdate se activa como se espera cuando se confirma la transacción.

¿Hay alguna manera de hacer que PreUpdate se active cuando se modifique una colección asignada? ¿O hay alguna otra técnica o anotación específica de Hibernate para detectar cuándo ocurre esto?

Respuesta

5

@PreUpdate evento se activa justo antes de que database UPDATE operation se ejecute para la entidad en cuestión.

Si no está actualizando las propiedades directas de Employee, no hay UPDATE para ejecutar para su tabla y por lo tanto @PreUpdate nunca se llama al oyente. Deberías tener mejor suerte al usar el evento @PrePersist que se desencadena por "flush" en lugar de "update".

+1

Estás en lo correcto. PrePersist tampoco ayuda, ya que se activa en INSERT y en este caso la recopilación se modifica una vez que la entidad ya se ha conservado. Supongo que mi pregunta realmente es preguntar si hay técnicas que funcionan de manera similar a PreUpdate para detectar cuándo se modifica una colección mapeada. –

+1

No estoy seguro de lo que quiere decir con "disparado en INSERT". ¿No estás llamando 'entityManager.persist (employee)' para guardar tu colección? Si no está (por ejemplo, confía en flush _only_), tendrá que configurar su propio oyente para uno (o más) eventos "flush"/"auto-flush"/"rubor-entity" (http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html#d0e500). O bien, para una solución específica de Hibernate, escriba su propio interceptor (http://docs.jboss.org/hibernate/stable/core/reference/en/html/events.html#objectstate-interceptors) - onFlushDirty() siempre llamado – ChssPly76

2

Tal vez una solución esta costumbre funciona:

crear una subclase de ArrayList que identifica los cambios a través patrón 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); 
    } 

    ..... 
} 
0

Aquí está mi aplicación para el proveedor de hibernación:

http://pastebin.com/8cPB96bZ

En general, solo marca los métodos que deberían llamarse en el caso de una colección sucia con @PreCollectionChan anotación ge

Cuestiones relacionadas