2012-06-27 11 views
6

¿Cómo puedo desprogramar un objeto de hibernación, de modo que el polimorfismo sería compatible?cómo desprogramar un objeto de hibernación

Considere el siguiente ejemplo. Las clases A y B son dos entidades de hibernación. B tiene dos subtipos C y D.

List<A> resultSet = executeSomeHibernateQuery(); 
for(A nextA : resultSet) { 
    for(B nextB : nextA.getBAssociations() { 
     if(nextB instanceof C) { 
      // do something for C 
     } else if (nextB instanceof D) { 
      // do something for D 
     } 
    } 
} 

Este código no se puede ejecutar ya sea el C o el bloque D, ya que la colección B ha sido perezoso cargado, y todos los casos de B son proxies de hibernación. Me gustaría una forma de desprocesar cada instancia.

Nota: Me doy cuenta de que la consulta se puede optimizar para buscar ansiosamente todas las B. Estoy buscando una alternativa.

+1

Sé que es una vieja pregunta, pero como apareció como el primer resultado en una búsqueda en Google, tendré que comentar aquí que si tiene que usar 'instanceof', entonces probablemente esté haciendo mal el polimorfismo. – drigoangelo

Respuesta

18

Aquí es nuestra solución, en nuestro utilidades de persistencia:

public T unproxy(T proxied) 
{ 
    T entity = proxied; 
    if (entity instanceof HibernateProxy) { 
     Hibernate.initialize(entity); 
     entity = (T) ((HibernateProxy) entity) 
        .getHibernateLazyInitializer() 
        .getImplementation(); 
    } 
    return entity; 
} 
+0

¿Esta solución funciona para usted? Implementé un método similar y todavía tengo un 'HibernateProxy' como clase de mi objeto. Aquí está mi pregunta: http://stackoverflow.com/q/11518091/845220 – woyaru

+0

Esto no aborda el problema de un 'PersistentCollection'. Por lo general, podría tener una 'List ' que en realidad ha sido proxificada como 'PersistentCollection'. Si se pasa por este método, la prueba 'instancia de entidad de HibernateProxy' fallaría y el método volvería sin hacer nada. Una solución sería también probar 'instance instance of PersistentCollection', usar' Hibernate.initialize() 'también, luego iterar y no ejecutar cada objeto de la colección. Más fácil de describir que implementar aunque ... – Aldian

+1

Tenga en cuenta que no necesita verificar que la entidad no sea nula (consulte http://stackoverflow.com/questions/2950319/is-null-check-needed-before-calling -instanceof) – laurent

2

La solución utilizando el HibernateProxy y la getImplementationMethod es correcta.

Sin embargo, supongo que se encontrará con esto porque su colección se define como una interfaz, e hibernate presenta los proxies a la interfaz.

Esto lleva a la pregunta de diseño, de por qué tiene el "si" con el "instanceof" en lugar de utilizar un método de interfaz para hacer lo que necesita.

Así que el bucle se convierte en:

for(B nextB : nextA.getBAssociations() { 
    nextB.doSomething(); 
} 

De esa manera, hibernar va a delegar la llamada a "doSomething()" al objeto implementación real, y nunca se sabe la diferencia.

+0

Todos los puntos buenos, y nuestro uso de la herencia es probablemente menos que ideal. En este caso particular, en realidad tenemos otra lógica dependiendo del tipo de cada elemento en la colección. Entonces, una cosa que podríamos haber hecho es agregar los métodos abstractos isC() e isD(), pero eso también se sintió un poco torpe. FWIW, nuestra jerarquía funciona para la mayoría de nuestros casos de uso, esto es parte del 20%. –

Cuestiones relacionadas