Currently Browsing

trabajo

La asociación unidireccional one to many a una clase hija da problemas en Hibernate

Después de muchas horas trabajando en el asunto, he descubierto que el Hibernate no trabaja bien con asociaciones unidirireccionales uno a muchos (one to many) donde el lado de los muchos es una clase padre y la asociación real quiere hacerse a una clase hija. Esto pasa cuando las clases hijas se modelan con una tabla separada cada una (quizá no pase cuando se hace con un discriminador, no lo he comprobado).

Por ejemplo, tengo una clase Calendario que se asocia en modo uno a muchos de forma unidireccional a una clase Componente. Componente es abstracta de modo que la relación solo tiene sentido con las clases hijas de Componente, en este caso, una clase Evento.

Lo que ocurre es que en la base de datos se modelan esas relaciones colocando una clave ajena (foreign key) en la entidad del lado de muchos. Sin embargo, cuando se recorre la relación desde el lado del uno, internamente se coge el lado de los muchos y se comprueba cuales de esos registros tienen como clave ajena a la entidad del lado del uno.

Sea como fuere, Hibernate decide no realizar esa comprobación teniendo en cuenta las clases hijas.

En la documentación advierte que este tipo de relación es bastante problemática y que se utilice una relación bidireccional. Dicho y hecho, la cosa ahora funciona sin mayores problemas.

Menudo quebradero de cabeza.

Patrones de diseño

Entre hoy y ayer en el trabajo he estado utilizando el patrón de diseño Visitor. Es mi primer encuentro directo con un patrón de la banda de los cuatro (GoF o Gang of Four), y mira que estuve pensando la solución un buen rato hasta que mi jefe me contó lo del patrón en cuestión, que explicaré brevemente a continuación.

El patron Visitor se utiliza cuando existe una clase padre A y una o varias clases hijas A1, A2, …, AN; todas tienen un metodo comun, por ejemplo metodo1() que realiza diferentes tareas dependiendo del tipo de la clase. ¿Para quá puede servir esto? Pues para iterar por una lista de clases A e hijas y llamar al metodo1 en cada clase.
El problema surge en que para recorrer la lista, el tipo del objeto (item) en cada iteracion debe ser de tipo A (el padre), y que si se llama a item.metodo1() ¡se ejecutara el metodo1 contenido en la clase padre! En lugar de lo correcto, que serí­a ejecutar el metodo1 de la clase hija a la que pertenezca el item.

La solucion consiste en crear un metodo accept(VisitanteA visitante) en todas las clases A e hijas que acepte un “visitante” (una clase de tipo VisitanteA). En el metodo accept se llama al método visit de la clase visitante que se paso como parametro, y el unico parametro del método visit es “this”, un puntero al objeto actual.

En la clase VisitanteA se implementa un método visit(A param), otro visit(A1 param), otro visit(A2, param), etc. Uno por cada clase que se quiera “visitar”. En ese método visit(Ax param) es dónde se ejecuta la lógica de nuestro antiguo método1(). De este modo, el Visitante “descubre” la clase del objeto, ya que el objeto se enví­a a si mismo y debido a la sobrecarga del método visit() se ejecutan las sentencias correctas.

Espero haberlo explicado medianamente bien. Por el momento he implementado como 4 o 5 clases visitantes. Tengo muchas herencias inusuales y restricciones semánticas en la base de datos que requieren del patrón. Todo esto me pasa por “mover” el modelo a la base de datos, en lugar de implementarlo en la lógica de negocio. Sin embargo, considero que este enfoque es mejor y más mantenible, aunque más laborioso. En fin, veremos como acaba el proyecto.

Problemilla con el JSFTAB

Bueno, pese a que el último post indicaba que el componente estaba funcionando con los facelets, no habí­a llegado a probar aún la navegación del mismo (que cuando se pulsan los tabs pues el componente cambie de página).

Entre mi jefe y yo estuvimos comprobando el código fuente del componente y llegamos a la conclusión de que el autor no lo tiene terminado. Tendrí­a que tener más cuidado cuando utilice componentes versión 0.2 pre-alpha, pero bueno. Le mandé un e-mail al autor pero como mirando el cvs parece que el tí­o dejó de actualizar el código hace 9 meses me da a mi que va a pasar de mi.

Tengo dos opciones, buscarme otro componente o arreglar éste. Me dedicaré a la segunda opción y asi de paso me entero de como funcionan los componentes internamente. Pero eso será mañana…

Pestañas y plantillas: jsftabs y Facelets

En este pequeño artí­culo describiré rápidamente como utilizar conjuntamente el componente jsftab de las Java Server Faces (disponible aquí­: https://jsftab.dev.java.net/) dentro de un sistema que utilice plantillas facelets.

Se presupone que tantolas facelets como el jsftab estan funcionando correctamente en el sistema por separado, de modo que lo que hay que hacer es decirle al servlet de los facelets que ejecute el tag del jsftab correctamente.

Basta con crear un fichero jsftag.taglib.xml dentro de /WEB-INF y rellenarlo con el siguiente código:


<facelet-taglib>
    <namespace>http://www.jsftab.com/jsftab</namespace>
    <tag>
        <tag-name>jsftab  </tag-name>
        <component>
            <component-type>com.jsftab.TabbedPanel</component-type>
            <renderer-type>com.jsftab.TabbedPanel</renderer-type>
        </component>
    </tag>
</facelet-taglib>

Seguidamente abrimos el web.xml e introducimos el siguiente parámetro de contexto que apunta al fichero
que acabamos de crear:


<context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>/WEB-INF/jsftab.taglib.xml</param-value>
</context-param>

Listo, todo deberí­a funcionar.