Pregunta

Editar el 5/11/2011:

Supongo que es un poco peor que lo que está debajo; en mi instancia de control de calidad implementada, si solo actualizo el panel principal varias veces, eventualmente se eliminan las asociaciones de grupo de muchos a muchos de mi usuario. En este punto, solo se invocan sentencias selectas en el lado del servidor; espero que lo esté reduciendo con estas últimas pruebas.

Original:

Hola a todos. Tengo un problema con un objeto bastante complejo; El problema es el siguiente: cuando envío el objeto del cliente al servidor para guardarlo, aparentemente está borrando al azar las relaciones de muchos a muchos en los objetos asociados. Peor aún, no soy capaz de reproducir el problema por mí mismo, después de aproximadamente dos meses de ser consciente del problema. Tengo la aplicación para probarla con un grupo de control de calidad; están usando el programa a diario, ingresando dos veces en las aplicaciones nuevas y heredadas. El problema surge hasta tres veces al día.

Haré todo lo posible para proporcionar todos los detalles que pueda y agradeceré mucho a cualquiera que eche un vistazo.

El marco de la aplicación es GWT 2.1 + Gilead + Hibernate 3 + MySQL InnoDB. Dejo que Hibernate maneje cualquier cascada, etc., por lo que ninguna está definida en la base de datos, aunque todas las claves externas están configuradas en la base de datos.

Aquí hay algunos extractos de las asignaciones:

<hibernate-mapping>
 <class name="com.example.domain.Close" table="CLOSE">

 <many-to-one name="updateUser"
class="com.example.domain.User"
column="LAST_UPDATE_USER"/>
 </class>
</hibernate-mapping>

<hibernate-mapping>
  <class name="com.example.domain.User" table="USER" batch-size="25">
    <set name="groups" table="USER_GROUP" lazy="true" batch-size="25">
      <key column="USER_ID"/>
      <many-to-many column="GROUP_ID" class="com.example.domain.Group"/>
    </set>
  </class>
</hibernate-mapping>

<hibernate-mapping>
  <class name="com.example.domain.Group" 
    table="GROUP" batch-size="25">
    <set name="users" table="USER_GROUP" lazy="true" inverse="true">
      <key column="GROUP_ID"/>
      <many-to-many column="USER_ID" class="com.example.domain.User"/>
    </set>
    <set name="permissions" table="PERMISSION_GROUP" lazy="true" inverse="true">
    <key column="GROUP_ID"/>
    <many-to-many column="PERMISSION_ID" 
      class="com.example.domain.Permission"/>
    </set>

<hibernate-mapping>
  <class name="com.example.domain.Permission" 
      table="PERMISSION">
    <set name="groups" table="PERMISSION_GROUP" lazy="true">
      <key column="PERMISSION_ID"/>
      <many-to-many column="GROUP_ID" 
        class="com.example.domain.Group"/>
    </set>
  </class>
</hibernate-mapping>

Guardar el objeto es una simple llamada a saveOrUpdate ():

Session session = gileadHibernateUtil.getSessionFactory()
  .getCurrentSession();
session.beginTransaction();
try {
  session.saveOrUpdate(close);
} catch (Exception e) {
  e.printStackTrace();
  session.getTransaction.rollback();
}
session.getTransaction.commit();

return close;

El 'updateUser' Close es un objeto que se carga cuando el usuario inicia sesión. Se carga con los grupos y permisos asociados para que el sistema pueda otorgar / denegar el acceso a los módulos de la aplicación. Yo hago

close.setUpdateUser(exampleApp.getUser()); 

antes de enviar el objeto al servidor.

Hay muchos otros lugares en la aplicación donde ocurre este tipo de operación, pero no causa los efectos secundarios no deseados. Probablemente se reduzca a la complejidad del código del lado del cliente asociado con el objeto Close, o más bien, a mi implementación.

He pasado tanto tiempo revisando los documentos oficiales de Hibernate, buscando posibles problemas relacionados, etc. Pensé que tal vez era un buen momento para pedir ayuda. Tengo que ser hombre y seguir haciéndolo, pero tal vez solo preguntar me ayude a resolverlo.

No estoy seguro de qué más proporcionar ahora que sea relevante. ¡Ojalá lo que hay aquí hasta ahora tenga relevancia!

¡Gracias por escuchar!

<×Editar

May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: insert into example_dev.RECENT_ITEM (OBJECT_TYPE, OBJECT_ID, DATE, USER_ID) values (?, ?, ?, ?)
May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: delete from example_dev.PERMISSION_GROUP where PERMISSION_ID=?
May  5 12:18:38 localhost last message repeated 19 times
May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: delete from example_dev.USER_GROUP where USER_ID=?
May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: delete from example_dev.USER_DESIGNATION where USER_ID=?

Parece que las eliminaciones están sucediendo justo después de esta inserción. Las operaciones anteriores son todas selecciones. Pero nada en User debería estar en cascada desde RecentItem.

¿Fue útil?

Solución

Después de mucha investigación, llegué a algunas conclusiones y pude tomar medidas. En primer lugar, aprendí después de buscar un poco en el foro de Gilead, que ya no es mantenido activamente . Debería haberlo notado antes. Mientras tanto, había comenzado a leer sobre RequestFactory y, después de un par de días de investigación, decidí que debería intentar migrar a esto.

Este es un proyecto bastante grande, aproximadamente 50 objetos de dominio, algunos con muchas asociaciones de objetos. Me tomó alrededor de 40-50 horas reescribir todo, desde usar Gilead + GWT RPC hasta usar RequestFactory exclusivamente. Estoy bastante contento con los cambios resultantes en el código y la estructura. Hasta ahora no me ha molestado mucho tener que crear objetos proxy DTO, y aproveché la oportunidad para cambiar a Hibernate Annotations, deshaciéndome de los archivos de mapeo.

A veces fue complicado refactorizar el código para utilizar los ciclos de búsqueda / edición / guardado que RequestFactory requiere. Me dio la oportunidad de mejorar parte del código.

La buena noticia es que el problema se ha resuelto. No más asociaciones de muchos a muchos que se eliminan misteriosamente. Mi mejor suposición es que estaba encontrando un error en Gilead, o mi uso era incorrecto, o es posible que haya resuelto un problema al migrar a Anotaciones.

Me encontré con algunos recursos excelentes mientras aprendía RequestFactory + Hibernate, muchos a través de StackOverflow (¡gracias de nuevo!):

Uso de GWT RequestFactory con Objectify - Fue genial tener una idea de cómo RequestFactory interactuaba con el backend, y algunos métodos y plantillas para reducir el código.

Espero que haya más enlaces a continuación ... Todavía soy un novato, así que tengo un número limitado de hipervínculos que puedo publicar :)

Aprendí mucho y estoy dominando RequestFactory. Haré todo lo posible para estar atento y ayudar aquí donde creo que puedo.

¡Gracias StackOverflow!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top