Dec 19

iBATIS

Al final creo que me he decidido por iBATIS. No he hecho más que unas pruebas sencillas con varios -Hibernate, iBATIS, JPOX, etc-, pero al final iBATIS me ha parecido el más "controlable".

Hibernate me ha fallado con la ingeniería inversa, no es capaz de tragarse el mismo los ficheros de configuración que él ha generado, aparte que los plugins y herramientas adicionales parecen bastante descuidadas.

JPOX ni siquiera he conseguido hacerlo funcionar -el plugin para eclipse, ni siquiera lo he probado a mano-. De todas formas, parece que toca los bytecodes después de compilar el código y eso me da "mal rollo".

iBATIS no me ha dado ninguna pega. El plugin para eclipse ha funcionado a la primera y el código generado funciona a la primera. Además, me gusta el tener los SQL visibles en un fichero, ya que siempre da la sensación de tener más control sobre lo que se está haciendo.

Un compañero mio probó cayenne, y aunque la ingeniería inversa se hace estupendamente con una interface gráfica de usuario, en los java beans mete cosas propias de él y no me convenció.

Por supuesto, y siguiendo mi costumbre, he puesto mis pruebas sobre iBATIS en la Chuwiki. Estoy deseando que me toque codificar algo contra una BD…

Nov 24

Creo que me he metido mucho con Hibernate

Sigo con mis pruebas de herramientas/librería de persistencia en base de datos.

Con Hibernate conseguí que funcionara. El ejemplo tonto con una única tabla funcionó casi a la primera. Las HibernateTools - Middlegen para sacar los .xml y los .java a partir de la base de datos me dieron más problemas, pero también funcionaron.

Luego hice pruebas con iBatis. La filosofía de trabajo es distinta, pero el plugin de eclipse me funcionó bien e iBatis genera código hasta un nivel más alto, genera una interface de DAO y una implementación iBatis.

Investigando, descubro que hay una especificación de Java, llamada JPA -Java Persistent API, parte V del tutorial de JEE-, que pretende indicar cómo trabajar con objetos java persistentes -que se guardan más o menos solos en base de datos, sin que el programador tenga que preocuparse de los SQL-.

También descubro que la gente de Apache ha hecho otra especificación similar, JDO, para lo mismo, pero que pretende ser más completa que JPA.

También descubro JPOX, una implementación que cubre las dos especificaciones anteriores: JPA y JDO. Sin embargo, no he conseguido que me funcione. Desde eclipse con el plugin correspondiente me falla al crear las tablas en base de datos y de momento me ha dado pereza crearlas a mano. En cuanto a maven, tienen una mezcolanza rara. Parece que se han quedado en maven 1 según la documentación, pero si te lo bajas con maven 2 está disponible, aunque no encuentro documentación para configurarlo.

Y descubro también que eclipse dali viene con una perpectiva y un "wizard" de proyecto para trabajar con objetos persistentes JPA. Por supuesto, tampoco me ha funcionado.

Y para marear más la perdiz, y todavía sin probar, Glassfish de java lleva una implementación de JPA, hay también otra implemantación de Apache OpenJPA,

En fin, todo un mundo y un abanico de posibilidades. Para probarlas todas no basta con que se paren dos meses la producción, harán falta varios años . De cualquier forma, Hibernate es uno de los que menos problemas me ha dado -descontando los de MiddleGen- y yo creo que sin duda es el más conocido. Aunque la filosofía de trabajo es distinta, iBatis también es conocido y da la impresión de que tienes más control sobre lo que estás haciendo. Ambos están "soportados" por SpringFramework -ver capítulo 12- que sí pienso empezar a usar, así que creo que me centraré un poco más en Hibernate e iBatis.

Nov 23

Hibernate, iBatis, JPA, …

¡ Menudo lío !

Siempre hemos programado nuestro código java contra base de datos en JDBC puro y duro. Llegamos a hacernos nuestro "equivalente" a herramientas como iBatis, pero usando siempre Hashtable para tener los resultados o hacer las inserciones y, desde luego, mucho más cutre que cualquiera de los anteriores. Eso sí, el nuestro construye sobre la marcha los paneles SWING y JTables para mostrar o modificar los resultados.

Sin embargo, ahora que me pongo a mirar un poco más en serio, veo multitud de herramientas similares que hacen cosas parecidas. Y ahí empieza la duda. ¿Cual usar?.

Hibernate parece el candidato más conocido y del que más se habla -al menos, eso me parece por lo que veo en los foros-. Sin embargo, en mis primeras pruebas, mis impresones no han sido muy buenas. Un sitio web relativamente caótico, unas Hibernatetools-middlegen más caóticas todavía. El plugin para eclipse no me ha funcionado. Veo que la "ingeniería inversa" de sacar los xml a partir de tablas creadas da problemas. Al menos a mí, con la primera base de datos seria que pruebo, los xml generados por la herramienta, luego dan error en Hibernate cuando trata de leerlos. Y veo que está demasiado pensado para Web y JEE. Sin embargo, la forma de trabajo desde código Java parece la más elegante y cómoda.

Ayer me puse a jugar un poco con iBatis. No llega, desde luego, al nivel de Hibernate, pero se le acerca. Además, en mis primeras pruebas me ha causado mejor impresión. El sitio web parece mejor organizado, las pruebas que he hecho me han funcionado rápido. Tiene un plugin abator de eclipse para a partir de tablas creadas en base de datos generar los beans, los DAO y los .xml de configuración. Hoy haré pruebas con tablas más en serio.

Y ayer también, me puse a mirar por encima JPA. Veo que también trabaja con beans simples de java -los llamans POJOs- que hace persistentes, al igual que Hibernate. Así que es otra que tendré que  mirar.

Y sigo con la duda. ¿Cual usar?. Cada vez estoy más convencido de que deberíamos parar todos los proyectos un par de meses para dedicarnos a hacer pruebas con este tipo de cosas y otros frameworks que hay por ahí. Seguro que recuperamos el tiempo con creces.

Nov 22

Día movidito con Hibernate

Ayer en el trabajo fue un día bastante movidito con el tema de Hibernate.

Me llevé de casa el build.xml y todos los jar necesarios para hacer allí una prueba, pero esta vez con una base de datos de verdad, con varias tablas "reales", en vez de mi tabla "Persona" de tres campos.

Por supuesto, como soy un cotilla y me gusta contarlo todo -valga este blog como prueba-, según iba haciendo experimentos, se lo iba contando a la gente. Al final había allí tres más conmigo haciendo pruebas. Emocionados con el tema, salí a las tantas.

Ahí van las pruebas y resultados que obtuve:

Elegí entre las las bases de datos que tenemos, una de tamaño medio en cuanto a número de tablas para hacer las pruebas. Debe tener entre 20 y 30 tablas -no las he contado- y muchas relaciones raras entre ellas.

Configuré el build.xml con los datos de la conexión y la primera parte, la de obtener los hbm.xml a partir de la base de datos fue como la seda. Sin ningún problema me saco los 20 ó 30 ficheros hbm.xml, uno por tabla.

Llegó el momento de generar los beans de java. Fallo estrepitoso. Daba un error bastante al principio y no generaba nada de nada. Después de un par de horas de pelearme con él, dí con el problema, increible donde los haya. Resulta que los ficheros hbm.xml llevan arriba, en la tercera o cuarta línea, una referencia al fichero dtd tal que así http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd . Hibernate-tool, cuando revisa ese fichero, intenta acceder a internet para coger ese fichero .dtd y poder comprobar si el XML es correcto o no. Pues bien, resulta que trabajamos a través de proxy que requiere usuario y password. Hibernate-tool no puede acceder a dicho fichero dtd y falla. Como no tenía ganas de empezar a ver si se puede configurar hibernate-tool para que trabaje a través de proxy, lo que hice fue bajarme todos los dtd que se mencionan en los ficheros .hbm.xml, e incluso los que se mencionan en el mismo dtd y ponerlos en mi ordenador -en total tres ficheros-. Luego, cambie todos los http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd por file:///d:/hibernate-mapping-2.0.dtd . Todo estupendo, generó los beans de java sin problemas aparentes.

La siguiente prueba, hacer el código java para consultar y sacar por pantalla la tabla principal de la base de datos.

Otro pequeño desastre. Al leer Hibernate sus ficheros .hbm.xml de configuración "casca". En casi todas las relaciones many-to-one me dice que hay un nombre de columna repetido y que debería ponerle insert="false" update="false". Así que nada, a mano, sin saber muy bien qué es lo que estoy haciendo, se lo pongo en los ficheros .hbm.xml en todos los sitios donde me va protestando el Hibernate al leer. Después de un rato -eran 20 ó 30 ficheros con varias relaciones en cada uno-, consigo que Hibernate lea la configuración y no "casque".

Pero, la siguiente en la frente. Al cargar la lista de beans asociados a la tabla principal -en el query()-, una excepción de un NullPointerException y/o un ClassCastException en una clave compuesta de una tabla de asociación que asocia un registro de la tabla principal con otro registro de la tabla principal. Ahí ya si me quedé bloqueado.

Hablando con el master del universo y de las bases de datos, me comenta que esa relación en esa tabla es válida, pero sí es cierto que es un poco extraña, ya que reutiliza las mismas claves primarias como …. -aquí un rollo técnico de BD que se me escapa totalmente-. En fin, que para probar, me quita esa relación. Vuelvo a repetir todo el proceso y todo correcto y funcionando.

¿Cual es el plan para hoy?. Pues aunque las que he encontrado están en versión alpha, voy a probar a realizar el proceso con hibernate-tool 3 en vez de con la versión 2.1, a ver si es capaz de tragar directamente con todo, sin necesidad de hacer cambios.

Al final, como dijo uno de mis compañeros, me da que esto de Hibernate va a servir para bases de datos de estructuras sencillas, sin complicaciones -no quiero decir pocas tablas ni pocos datos, sino simplemente que no tengan "virguerías" en las relaciones-. Supongo que tendré que hablar con el responsable de las bases de datos para que las futuras bases de datos que nos hagan no lleven demasiadas cosas raras.
 

Nov 21

Por fin, generados los beans con Hibernate

Por fín. Me ha costado un horror, pero lo he conseguido. A partir de la base de datos, he conseguido generar los ficheros hbm.xml de hibernate y a partir de ellos, el código java de los beans.

Al final tuve que hacerlo con ant y aún así ha costado. En ningún sitio te pone claramente el proceso y los jar necesarios están escondidos por el internet.

Aunque haré un pequeño ejemplo más detallado en la Chuwiki cuando me aclare qué es exactamente lo que he hecho, aquí va un pequeño avance.

Generar los hbm.xml a partir de la base de datos

Para generar esto, además de algunos .jar que se nos colarán, necesitamos los jar de hibernate core y los de middlegen. De este último hay una versión 3.x, pero creo que está en un estado muy "alpha".

Los .jar que se nos pueden colar son, por supuesto, el driver java de la base de datos que usemos y a mí me ha hecho falta un velocity-x.x.jar. Hay un pequeño truco para sacar todos estos jars raros que no vienen en ningún lado. Dentro de middlegen, hay un directorio samples con un subdirectorio lib. Ahí están todos los que necesitamos. Es curioso que esta gente no ponga todos los jar necesarios en la herramienta, pero sí los ponga en el ejemplo.

Una vez que tenemos todo, hay que hacerse un build.xml similar al que aparece en la página de middlegen, el primero que aparece de ejemplo. Por supuesto, luego hay que andar arreglándolo para nuestros paths concretos. Una vez arreglado todo, se ejecuta ant. Este se conecta a la base de datos y nos crea los ficheros hbm.xml, uno por tabla.

Generar los fuentes de los bean java a partir de los hbm.xml

Para esto segundo, necesitamos además dos misteriosos y escondidos jars: hibernate-tools.jar y freemarker.jar. Estos son los que más "por el …" me han dado. No había manera de econtrarlos por ningún sitio.

El sitio que aconseja en la página es descargarse hibernatetools, en su versión plugin para eclipse. Una vez desempaquetado el plugin de eclipse, nos vamos al directorio plugins/org.hibernate.eclipse_3.2.0.cr1/lib/tools/ y listo, ahí tenemos las famosas hibernate-tools.jar tan necesarias.

Por supuesto, también nos vale el truco de antes. Nos vamos al directorio samples/lib de middlegen y ahí también lo tenemos.

Finalmente, hay que hacerse otro build.xml -o juntarlo con el anterior- en el que he puesto esto -no recuerdo de dónde lo he sacado

<target name="hbm2java">
<taskdef name="hibernatetool"
    classname="org.hibernate.tool.ant.HibernateToolTask"
    classpathref="lib.class.path"/>
<hibernatetool destdir="path_donde_dejar_los_fuentes">
 <configuration>
   <fileset dir="path_donde_estan_los_hbm_xml">
    <include name="**/*.hbm.xml"/>
   </fileset>
 </configuration>
 <hbm2java/>
</hibernatetool>
</target>

y nada, funcionó. Me generó los beans java correspondientes a las tablas.

Nov 19

No sé yo Hibernate…

Pues nada, veo que Hibernate tiene muy buena pinta, si haces lo que él quiere.

Dicho de otra forma. Tú te generas tu fichero de configuración de hibernate, con él generas la base de datos -y los beans creo- y todo estupendo y maravilloso.

Pero, ¿qué pasa si ya tienes la base de datos creada de antes?. Nada más fácil, te haces el fichero de configuración de hibernate a mano y todo estupendo y maravilloso.

Pero, ¿qué pasa si la base de datos tiene mogollón de tablas con tropecientas columnas cada una?. Pues tampoco pasa nada, hay una cosa que se llama ddl2hbm que ya está obsoleta, pero que ha sido reemplazada por otra que se llama middlegen que hace justamente eso que quieres. Coge una base de datos y genera el fichero de configuración de hibernate. Todo estupendo y maravilloso.

Vaya. Veo que lo de middlegen está pensado para funcionar con ant. Ejecutarlo requiere que tengas ant, que sepas ant y que configures un build.xml con una decena de propiedades. A ver si encuentro algo más sencillo.

Middlegen también tiene un plugin para eclipse, el middlegenide. Tiene buena pinta. Lo instalo. Después de diez minutos -o media hora- de rebuscar por eclipse encuentro desde dónde lanzarlo: "file" -> "new" -> "other" -> "middlegen" … y con eso se supone que consigo… un build.xml de ant. Relleno los datos que me pide el formulario y obtengo un error de lo más descriptivo -ver foto-

error

Y con eso, claramente, sé sin lugar a dudas qué es lo que ha fallado. Acepto el error -pulso OK- y lo arreglo

Así que nada, a  buscar otra opción. Veo también que hay plugin de maven. Lástima, parece que es para maven 1 y yo tengo maven 2. No sé dónde demonios tengo que configurar los datos de conexión a base de datos, ya que el project.properties creo que no existe en maven 2. Tampoco tengo demasiadas ganas de abrir recursivamente una segunda investigación de dónde meter en maven2 el project.properties para configurar el plugin de maven de middlegen para ver cómo funciona este plugin con una base de datos…. Bufff.

Sigo investigando y me encuentro otro plugin de eclipse: HiberClipse. Este es mejor todavía. Ni suquiera he conseguido instalarlo. El "update manager" o como demonios se llame, se va a la URL que dice allí y no encuentra nada de nada para instalar.

En fin, me tendré que dedicar un par de horitas a recordar ant, configurar el dichoso build.xml a mano y rezar para que salga algo.

Nov 18

Jugando con Hibernate

Me he puesto a jugar un poco con Hibernate y me ha encantado, aunque también he empezado a odiar ciertas cosas.

Primero intenté crear un proyecto maven con hibernate, para obtener los jar de forma automática. Por ahí surgieron mis primeros poblemas. Encontré en el repositorio maven un groupId "hibernate" y otro "org.hibernate" y, por supuesto, en el primer intento me equivoqué.

En org.hibernate -el que al final usé- otra sorpresa. Los números de versión son raros porque llevan una letras detrás, por lo que ya no sabes qué bajarte. Si no hay letras, está claro, el último número, pero con letras…. Me decido por uno. Mis segundos problemas y comienzos del odio fue que no se bajó el jta.jar. Eso, hasta cierto punto es normal. El jta.jar es de sun y sun no permite que otros distribuyan sus jar. Hay que ir a la página de sun y bajárselo. Me voy a la página de sun … y jta.jar pertenece al paqute JEE. ¿Por qué me tengo que bajar JEE si sólo hago aplicaciones de escritorio?.

No obstante, intenté bajarme e instalar JEE … en linux. Error al desempaquetar el paquete porque me falta no sé qué ¿versión concreta, con números, de una librería de C++?. ¿Tengo que tener instalada una versión concreta de la librería C++ para desempaquetar JEE?. ¡¡ Paso de JEE !!. ¡A ver si al final tengo que recompilar el kernel!

Me fuí a la página de Hibernate y me bajé Hibernate core. Me costó un buen rato decidir qué bajaba. No conozco Hibernate, pero sí sé lo que quería: ¡No depender de JEE!. Tarea casi imposible. En cualquier sitio de Hibernate que te metas, por mucho J2SE que ponga en el enlace, empieza a mencionar EJBs y JBoss.

Bueno, ya he protestado bastante. No me gusta nada la página de Hibernate, no me parece clara y hay que darle demasiadas vueltas hasta encontrar lo que quieres. Vamos ahora con lo bueno.

Como dije, me bajé Hibernate core y ahí sí venía el jta.jar y por suerte, no venía el JEE. ¿Por qué sun deja distribuir a Hibernate su jta.jar y no deja a Maven?. Luego, un ojo a la documentación para seguirla y tratar de hacer algo.

Y ahí empecé a maravillarme de sus posibilidades.

Por un lado, según Hibernate hay tres formas de definir la base de datos. Podemos tener la base de datos en sí. Podemos hacer un fichero xml al estilo Hibernate en que se relacionen tablas de base de datos con beans de java y las columnas de las tablas con los atributos del bean. Y finalmente, podemos tener beans java con "annotations". Eso de las annotations no es más que poner encima de los atributos java cosas como @id, @column de forma que con esto indicamos qué es cada atributo del bean en la base de datos.

Primera maravilla. A partir de cualquiera de esas tres, Hibernate es capaz de generar las otras dos. Si yo escribo el fichero xml, Hibernate crea las tablas en base de datos y el código java de los beans. Si tengo la base de datos, Hibernate crea el fichero xml y los fuentes java de los beans. Y si tengo ya los beans hechos, con sus annotations, Hibernate crea las tablas de base de datos de y el fichero xml. Por supuesto, todo eso opcional. En mi caso, las tablas de datos en el trabajo están hechas. Sacaría de ellas el xml y los beans.

Por supuesto, permite relaciones entre beans/tablas de las típicas uno a uno, uno a muchos, muchos a muchos. En los beans java simplemente son atributos Hash, List o lo que sea y en las tablas incluso crea las tablas intermedias con los dos índices de las relaciones.

Unas peguillas: Lo de generar la base de datos a partir del xml, en el ejemplo que pone la documentación viene que se haga automático. Así que mi primera prueba se cargó la tabla de base de datos que tenía, con sus datos, y me la creo de cero. Ahí que tener cuidado con estas cosas. La otra peguilla es que para esto necesitas "Hibernate tools", pero entre que viene para usar con ant o como plugin de eclipse que no me ha funcionado de momento, pues de momento no soy capaz de hacer nada de eso -salvo cargarme la base de datos la primera prueba-. Es la primera herramienta que veo que dan la opción "destructiva" fácilmente accesible como ejemplo y las opciones "constructivas" escondidas entre scripts crípticos de ant.

Segunda maravilla. Una vez configurado todo, desde código java puedo obtener a través de Hibernate un bean correspondiente a un registro de una tabla. Pues bien, cualquier modificación en los datos que haga de ese bean en el código java, se refleja automáticamente en la base de datos. Cuando termine las modificaciones, puedo hacer un commit() o un rollback() para confirmar o cancelar los cambios. Con Hibernate, en un momento dado, podemos olvidarnos totalmente de que hay una base de datos detrás y de todas las sql, salvo, quizás, para la carga inicial de datos. Los beans son realmente persistentes en BD, sin necesidad de código separado para insertarlos o modificarlos en base de datos.

Seguiré investigando y jugando con el tema porque creo que sí que merece la pena usar una herramienta como esta. Me da "cosa" que esté tan "casada" con JEE y JBoss. También me dan las dudas de eficiencia luego en tiempo de ejecución, pero hasta que no se pruebe, no se sabe. En cualquier caso, sólo con que de una tabla de BD te saque el código java de los beans, ya merece la pena.