Wednesday, March 9, 2011

JPA: S'ha acabat el pensar en relacional

Quan tens una base de dades i coneixes SQL tots els problemes els penses en termes relacionals: taules, consultes, inserts, deletes, etc. Si necessites una dada, fas una query. Si la dada és a una altra taula, fas una JOIN.

A una aplicació Java tot ho has de pensar en termes d'objectes, defineixes les seves relacions i la seva jerarquia. Si has d'accedir a una base de dades relacional des de Java, ja tens el mal de cap.

D'entrada la API d'accés a dades, el JDBC, és molt ferragossa. I per altra banda tenim el clàssic problema del "impedance-missmatch", que no podem mapejar directament una jerarquia d'objectes a un model relacional. I a això l'has de sumar que si estàs fen consultes de, diguem Empleats, cada vegada que obtens un Empleat faràs un nou objecte que després quedarà a disposició de la màquina virtual per ser alliberat. Un malbaratament que et fa pensar en l'ús d'alguna caché.

Per totes aquestes coses han sortit moltes solucions de mapeig Objecte-Relacional, els coneguts ORM. Després d'haver provat TopLink i Hibernate, he topat amb JPA, Java Persistence API.

D'entrada JPA pertany a l'estàndard JEE (tot i que ha estat creat a la mida d'Hibernate) i permet fer servir tots els recursos dels Entity Beans sense fer servir Entity Beans.

Fent servir annotations (que són aquelles coses que porten una @ i es posen abans de la definició de la classe, de l'atribut o del que sigui) marques tota la configuració de la teva entitat. Un @Entity abans de la teva classe, i un fitxer de configuració persistence.xml i ja tens mapejada una taula a la teva classe. Tens mètodes per obtenir un registre per identificador (em.findById(...)) i cada vegada que modifiques l'objecte que has recuperat es converteix en un update.

Per sota JPA farà servir un Persistence Provider, una implementació concreta. He vist que hi ha una d'EclipseLink i una altra d'Hibernate, i cal anar en compte si fas servir alguna de les extensions pròpies. Només he provat la d'Hibernate.

El codi final queda super net i fàcil de llegir. Però tot no podia ser tan bonic.

Fer un mapeig d'una taula, és immediat. Mapejar una jerarquia, o un Empleats-Departaments (on cada Departament té una llista dels Empleats que treballen) ja posa les coses més difícils. I altres coses, senzillament no es poden fer.

Si es tracta de construir una aplicació sobre un model de dades existent la recomanació és adaptar-lo: construir les vistes o el que calgui per tal de facilitar-li la vida a JPA. Moltes vegades no hi ha prou amb vistes, per què necessites noves taules amb noves seqüències.

El disseny de la BD per una aplicació que ha de fer servir un ORM (sigui JPA o el que sigui) ha d'anar de la mà del disseny dels objectes. Em costa molt pensar d'aquesta manera, però certament quan dissenyes una BD has de tenir en compte la manera com es farà servir. De fet, les desnormalitzacions són necessàries quan coneixes quin ús tindrà la BD, no abans.

El problema que li veig és que el model de dades que li vindrà bé a JPA segurament no serà bo per alguna altra tecnologia més clàssica. I l'altre problema és que per que aquests muntatges siguin eficients cal muntar una caché d'objectes, i si tens aquestes cachés ja no pots accedir o modificar les dades des d'una altra tecnologia. Invalidem el concepte "altra tecnologia". Fins i tot potser que invalidis els triggers o les constraints.

JPA, i altres ORM, intenten apropar las bases de dades relacionals a les aplicacions Orientades a Objectes. No és una solució ideal, però de moment és el millor que m'he trobat.

No comments: