3. Bases de dades Orientades a Objectes
1. Base de dades Orientades a Objectes. ObjectDB
En aquesta secció, com a SGBD, s'ha escollit ObjectDB, ja que és molt versàtil, gratuït i fins i tot permet incrustar-lo dins dels nostres projectes Java, cosa que permet una gran simplicitat per al desenvolupament de petites aplicacions, gràcies a l'eliminació d'un servidor.
2. Instal·lació
ObjectDB no requereix instal·lació com a tal, ja que tot el seu codi està integrat en una API per accedir a la base de dades empaquetada en un fitxer jar. Des del lloc web oficial podem descarregar el Kit de Desenvolupament d'ObjectDB. En el moment d'escriure aquest llibre, la versió és la 2.9.0. Aquest kit conté, entre altres:
- Dependències per a projectes Java
- Utilitats per visualitzar i consultar la base de dades
- Servidor per a aplicacions distribuïdes
- Documentació
Un cop descomprimit, només necessitarem la màquina virtual Java instal·lada al nostre sistema per executar tots els elements. Per utilitzar ObjectDB en el nostre projecte hem d'afegir el fitxer objectdb.jar a les dependències del nostre projecte o fer-ho utilitzant el gestor de dependències maven o gradle.
En aquest moment podem connectar-nos a la base de dades, la centralització de la connexió a la base de dades es fa a través d'una instància d'un objecte EntityManagerFactory, del qual podem obtenir diverses instàncies d'un EntityManager.
Des de l'EntityManager podrem dur a terme les operacions típiques de CRUD, tenint en compte que sempre que hi hagi modificacions en ell. Hem de dur a terme l'operació dins d'una transacció per evitar situacions inconsistents en ella. Aquí veiem una possible classe amb l'establiment de la connexió i l'obtenció d'un EntityManager. Aquest codi es pot veure en el fitxer adjunt ConexionOBD.java. Tingueu en compte que les importacions són de javax.persistence:
3. Persistència de classes
Per persistir un objecte, necessitarem (semblant a Hibernate):
- Anotar la teva classe i marcar-la com a
@Entity - Definir un camp com a
@Idi opcionalment auto-incrementar amb@GeneratedValue. - La resta dels atributs de l'entitat, per defecte, es persisteixen automàticament sense cap tipus d'anotació. En cas de no voler persistir-ne, podem indicar-ho amb
@Transient.
| Java | |
|---|---|
Per emmagatzemar un Alumne, n'hi haurà prou amb crear un Alumne i persistir-lo a la base de dades, com es veu a continuació, assumint l'objecte de tipus conexionDB vist en el fitxer adjunt:
| Java | |
|---|---|
Classes incrustades o Components
En Java, de vegades hi ha classes que no tenen existència pròpia, tret que existeixin dins d'una altra classe, com ara una classe Adreça. No té sentit crear un objecte Adreça ad-hoc, en canvi, sí que té sentit crear-lo perquè una Adreça existeixi, per exemple, dins d'un Estudiant.
Per a aquests casos (febles) que existeixen incrustats dins d'altres classes, hem de declarar-los com a incrustables utilitzant l'anotació @Embeddable i marcar-los com a incrustats (@Embedded) dins de la classe en què existeixen.
| Java | |
|---|---|
Una entitat Alumno es guardarà a la base de dades, però la Direccion no existeix com a objecte per si mateix.
4. Relacions
4.1. Relació un a un
La relació més senzilla és un a un, en la qual un objecte conté un altre objecte. La marcarem com ja ho vam fer en Hibernate amb el modificador @OneToOne indicant que el desament és en cascada (cascade=CascadeType.PERSIST).
A partir d'ara, quan desis una instància d'un objecte, la teva pròpia instància de l'objecte relacionat es desarà i s'enllaçarà. L'objecte enllaçat tindrà existència per si mateix (si està marcat com a @Entity). Un exemple bàsic en què una classe té un únic Tutor:
Basat en un exemple en què una Clase (d'un institut) té un Tutor associat, l'exemple serà el següent:
| Java | |
|---|---|
Atenció
Recorda que, de la mateixa manera que en Hibernate, aquesta relació és unidireccional, però es pot fer bidireccional.
4.2. Relació Una a molts
Ara ens referirem a una relació clàssica en la qual un Professor és el tutor de diversos Alumne. Aquestes relacions poden ser unidireccionals o bidireccionals. En aquest exemple ho veurem de manera bidireccional, de tal manera que donat un alumne podem saber qui és el seu tutor i donat un professor podem obtenir els alumnes que tutoritza.
| Java | |
|---|---|
Atenció
Recorda que, de la mateixa manera que en Hibernate, la càrrega de les col·leccions es pot fer immediatament, amb una mode EAGER o quan sigui necessari en mode LAZY.
4.3. Molts a molts
En les relacions de molts a molts, podem abordar-les de diverses maneres. Donem l'exemple de l'ensenyament entre Professor i Alumne. Si simplement volem indicar qui ensenya a qui, seria suficient emmagatzemar una col·lecció de professors en cada alumne (els professors que ensenyen a aquest alumne), i simètricament, en cada professor una col·lecció d'alumnes (els alumnes a qui ensenyen). En aquest cas, seria bidireccional, ja que des d'una classe podem navegar a l'altra, quedant així:
| Java | |
|---|---|
Atenció
Si necessitem desar qualsevol informació dins d'aquesta relació, com ara la nota que s'ha rebut, l'estudiant, o els incidents publicats, etc., llavors hem de crear una nova classe, que incorporarà els atributs de la relació, i establir relacions un a molts des de cada entitat (Estudiant/Professor) fins a la nova entitat (Ensenyament). Aquesta suposició és la famosa Les relacions N-M generen una taula amb els atributs que posseeixen del model relacional.
5. Consultes
Revisarem com podem carregar les dades que hem desat prèviament a la base de dades. Suposem que tenim una classe Estudiant, mapada amb una entitat i amb un identificador (idStudent). La manera més senzilla de carregar un Estudiant, coneixent el seu id, és el mètode find(class,id), com vam fer a Hibernate:
| Java | |
|---|---|
La resta de les càrregues s'han de dur a terme mitjançant consultes, en un llenguatge JPQL (Java Persistence Query Language), novament similar a l'HQL de Hibernate.
Hi ha dues classes: Query i TypedQuery (la segona hereta de la primera), que s'utilitzen normalment en el primer cas quan no coneixem el resultat de la consulta, i en el segon quan coneixem el resultat.
La primera és polimòrfica, de manera que enllaçarà dinàmicament els resultats, i la segona verifica el resultat amb la classe actual. La documentació oficial recomana l'ús de la segona, TypedQuery per a consultes i Query per a actualitzacions i eliminacions.
De manera similar a Hibernate, podem consultar la base de dades de la següent manera:
| Java | |
|---|---|
o amb paràmetres:
| Java | |
|---|---|
o crear consultes amb nom específiques:
5.1. Esborrats i Actualitzacions
Finalment, revisarem les últimes operacions CRUD que ens queden. Les actualitzacions són totalment transparents per a l'usuari, ja que qualsevol modificació que es faci dins del context d'una transacció es desarà automàticament quan es tanqui amb un commit(). Alternativament, es poden realitzar consultes d'actualització.
Per a les eliminacions, si l'objecte s'ha recuperat de la base de dades, i per tant està en la transacció actual, es pot eliminar amb em.remove(object). Es eliminarà de la base de dades quan es faci el commit.