2010-06-19 12 views
7

tengo relación:Actualizar lista OneToMany después entidad salvo en hibernación

// In A.java class 
@OneToMany(mappedBy="a", fetch=FetchType.LAZY) 
@Cascade(CascadeType.SAVE_UPDATE) 
private List<B> bList; 

// In B.java class 
@ManyToOne(fetch=FetchType.LAZY) 
@JoinColumn(name="id_a") 
@Cascade(CascadeType.SAVE_UPDATE) 
private A a; 

Ahora mira esto:

A a=new A(); 
// setting A 

B b=new B(); 
// setting B 
b.setA(a); 

session.save(b); // this save b and a obviously 

Ahora el "problema":

  • a.getId() -> ID actual nuevo OK
  • a.getBList() -> still null ...

Entonces, ¿por qué bList no se actualiza en este caso?

Traté de volver a cargar una después de guardar, de esta manera:

A a=new A(); 
// setting A 

B b=new B(); 
// setting B 
b.setA(a); 

session.save(b); 

A loadedA=(A)session.get(A, a.getId()); 

Pero loadedA todavía tienen un NULL como un ListaB.

Naturalmente para evitar este problema te gusta hacer en tu camino:

A a=new A(); 
// setting A 

B b=new B(); 
// setting B 

List<B> bList=new ArrayList<B>(); 
bList.add(b); 
a.setBList(bList); 

session.save(a); // this save a and b 

De esta manera todo el trabajo bueno, pero mi pregunta es: ¿Por qué la identificación es correcta actualización después de guardar el funcionamiento y ListaB no? Tengo que consultar db con una instrucción select para volver a cargar una instancia correctamente?


ACTUALIZACIÓN

tengo esta excepción

StaleStateException: actualización por lotes volvió recuento de filas inesperado de actualización

cuando intento saveOrUpdate entidad un después borrando b de él.

// first delete old b record 
Session session=HibernateUtil.getSessionFactory().getCurrentSession(); 
session.beginTransaction(); 
a.getBList().remove(b); 
b.setA(null); 
session.delete(b); 
// session.clear(); // this would solve my problem, but is it correct?? 
session.getTransaction().commit(); 

// then insert new b record 
Session session=HibernateUtil.getSessionFactory().getCurrentSession(); 
session.beginTransaction(); 
B b=new B(); 
a.getBList().add(b); 
b.setA(a); 
session.saveOrUpdate(a); 
session.getTransaction().commit(); // this throw exception 

esta operación de dos no están en el mismo método por supuesto, son disparados por eventos GUI.

session.clear es la verdadera solución? Estoy haciendo (probablemente) mal?

actualización

eliminación Session.delete (b) el problema se resuelve de nuevo ... así que, ¿cuál es la forma corretc? lo sé ... im totalmente noob con Hibernate ..

Respuesta

4

Ah ... ok

session.refresh(a); 

Este buen trabajo ... Es esta la solución, no es cierto?

+1

Blow, Aquí http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html # objectstate-transitive puede obtener una buena idea sobre qué método de persistencia usar al utilizar en cascada –

6

Cuando se trabaja con asociaciones bi-direccional, lo que tiene que establecer el enlace en ambos lados de la asociación:

A a = new A(); 
B b = new B(); 
a.getBList().add(b); 
b.setA(a); 

session.persist(b); 

Y, de hecho, el patrón común es poner en práctica los métodos defensivos de gestión de enlaces de este tipo:

public class A { 

    @OneToMany(mappedBy="a", fetch=FetchType.LAZY) 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private List<B> bList = new ArrayList<B>(); 

    protected List<B> getListB() { 
     return bList; 
    } 

    protected void setListB(List bList) { 
     this.bList = bList; 
    } 

    public void addBToBs(B b) { 
     bList.add(b); 
     b.setA(this); 
    } 

    //... 
} 

Y el código se convierte en:

A a = new A(); 
B b = new B(); 
a.addBToBs(b); 

session.persist(b); 

Esto se discute en el Tutorial de hibernación:

+0

gracias Pascal – blow

+0

@blow: De nada. –

+0

actualización .......... – blow

Cuestiones relacionadas