hibernate elimina la relación de la lista al actualizar otra lista que contiene los mismos objetos

En mi aplicación tengo una configuración como la siguiente:

class A {
    String id;
    List<C> list;
}

class B {
    String id;
    List<C> list;
}

class C {
    String id;
}

que está mapeado en hibernación como

<class name="A" lazy="false">
    <id name="id">
        <generator class="org.hibernate.id.UUIDGenerator"/>
    </id>
    <list name="list" lazy="false" mutable="false">
        <key column="listA_id"/>
        <list-index column="listA_index"/>
        <many-to-many class="C"/>
    </list>
</class>

<class name="B" lazy="false">
    <id name="id">
        <generator class="org.hibernate.id.UUIDGenerator"/>
    </id>
    <list name="list" lazy="false" mutable="false">
        <key column="listB_id"/>
        <list-index column="listB_index"/>
        <many-to-many class="C"/>
    </list>
</class>

<class name="C" lazy="false">
    <id name="id">
        <generator class="org.hibernate.id.UUIDGenerator"/>
    </id>
</class>

Las 5 tablas (una para cada clase y 2 para las relaciones de muchos a muchos) se crean como se esperaba. El problema aparece cuando ejecuto algún código como el siguiente:

A a = new A();
B b = new B();
C c1 = new C();
C c2 = new C();
C c3 = new C();

<hibernatesession>.save(c1);
<hibernatesession>.save(c2);
<hibernatesession>.save(c3);

a.list.add(c1);
a.list.add(c2);

<hibernatesession>.save(a);

b.list.add(c1);
b.list.add(c3);

<hibernatesession>.save(b);

Seguí el SQL resultante en un archivo de registro HSQL y encontré que todo estaba bien hasta el último guardado. Al guardar b, la asociación entre a y c1 se eliminará de la lista A_de muchas-muchas-tablas. Recuperar los objetos a y b nuevamente de la base de datos dará como resultado que c1 y c3 estén en b.list pero solo c2 en a.list.

Observaciones: * No hay cascada en el juego. * cambiar el orden de guardar a/b dará como resultado que c1 se elimine de la lista de quien se guarde primero. * Ambas listas están mapeadas con índices. * Ambas listas están asignadas con diferentes nombres de columna clave/índice. * hibernate elimina exactamente los elementos comunes a las listas

¿Alguien puede explicarme este comportamiento de hibernate y sabe cómo realizar correctamente un mapeo respectivo?

Gracias por adelantado!!! Salsolatragus

preguntado el 03 de mayo de 12 a las 15:05

2 Respuestas

Intente agregar un mapeo de muchos a muchos a la Clase C para que sea una relación bidireccional. Quizás al ser explícito acerca de las relaciones "principales", sabrá mantener más de una relación en lugar de eliminar la primera como ha explicado.

<class name="C" lazy="false">
    <id name="id">
        <generator class="org.hibernate.id.UUIDGenerator"/>
    </id>
    <list name="listA" lazy="false" mutable="false" inverse="true">
        <key column="listC_id"/>
        <many-to-many class="A"/>
    </list>
    <list name="listB" lazy="false" mutable="false" inverse="true">
        <key column="listC_id"/>
        <many-to-many class="B"/>
    </list>
</class>

contestado el 03 de mayo de 12 a las 16:05

Lo intenté, pero sigue siendo el mismo fenómeno... excepto que él es no eliminando las referencias hacia atrás! Entonces c1 mantiene su referencia en un y b, mientras que cualquiera de ellos pierde su referencia a c1. De alguna manera esto me parece aún más extraño... - Sven Amann

Se corrigió el error. Lecciones aprendidas: si tiene correlaciones extrañas entre ciertas colecciones en hibernación, verifique primero si está usando accidentalmente la misma instancia de Java para ellas... Un par de horas de depuración a través de hibernación finalmente nos llevaron a la conjetura correcta. Cosa complicada. Problema resuelto.

¡Gracias por tu pista, Brad!

contestado el 04 de mayo de 12 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.