# Mapatge objecte-relacional
## Què és ?

El mapatge objecte-relacional és una tècnica que té com a finalitat principal facilitar la tasca d'emmagatzemar i recuperar objectes d'un llenguatge de dades orientat a objectes en bases de dades relacionals.
Vam indicar al començament d'aquest curs que les variables d'un objecte son les que guarden el seu estat, de forma que són aquestes les que s'han d'emmagatzemar a la base de dades per a poder recuperar l'objecte en les mateixes condicions que quan es va guardar.
Hi ha estudis que conclouen que el 35% del codi d'una aplicació que utilitzi alguna mena de mecanisme de persistència d'objectes, està relacionat amb aquest aspecte. L'ús d'aquestes tecniques és, per tant, un factor molt important de reducció del cost de construcció d'una aplicació.

## Hibernate

Hibernate és un mapejador objecte-relacional de codi obert.
El seu funcionament es basa en la creació d'un fitxer de configuració, anomenat fitxer de mapatge, per a cada classe que es vol emmagatzemar a la base de dades. Aquest fitxer relaciona la classe amb una taula de la base de dades i cada variable de la classe amb una columna d'aquesta taula.
D'aquesta forma, cada cop que es vulgui emmagatzemar o recuperar l'objecte a la base de dades, Hibernate genera tot el codi SQL necessari, i el programador no deixa mai de treballar en un llenguatge orientat a objecte.

## Funcionament

Per tal de fer que una classe es pugui emmagatzemar i recuperar de la base de dades amb Hibernate, ha de complir tres requisits:
* Disposar d'una variable que pugui actuar com a identificador únic de l'objecte. Aquest identificador el generarà Hibernate, de forma que no serà manipulat pel nostre codi.
* Disposar d'un constructor sense arguments.
* Disposar, per a cada variable de la classe, d'un mètode per a donar-li valor i un altre per a obtenir-lo. Aquests mètodes s'anomenen setters i getters respectivament i han de començar amb la paraula set i get seguida del nom de la variable a la que donen o consulten valor, amb la primera lletra en majúscules.
Exemple: Fem la classe TipusAvio candidata a ser persistent amb Hibernate

## El fitxer de mapatge

Un cop una classe reuneix les condicions per a poder ser persistida per Hibernate, haurem de crear el fitxer de mapatge que indica com ha de ser emmagatzemada a la base de dades.
Aquest fitxer ha de tenir el mateix nom que la classe, afegint l'extensió .hbm.xml i per tal que Hibernate el trobi, s'ha de situar al mateix directori on estarà la classe un cop compilada.
En el nostre cas, situarem els fitxers de mapatge al directori conf/, creant sobre aquest l'estructura de directoris ca/udl/estiu. Amb Ant farem que cada cop que compilem els fitxers de mapatge es copiïn al directori build/classes/ca/udl/estiu/, on estaran les classes compilades del nostre projecte.
Exemple: Fitxer de mapatge de la classe TipusAvio
Les etiquetes
corresponen a l'estructura exterior del fitxer de mapatge.
La primera etiqueta que ha de contenir aquesta estructura és la que indica a quina classe correspon el fitxer i en quina taula de la base de dades es guardarà.
En aquest cas veiem que el nom de la classe a la que correspon aquest fitxer és TipusAvio i que la taula de la base de dades on es guardaran els objectes d'aquesta classe s'anomena TIPUSAVIO.
A continuació donem a Hibernate la propietat que volem utilitzar com identificador únic (id) dels objectes d'aquesta classe, especificant de quin tipus és (en aquest cas int) i en quina columna de la base de dades persistirà (en aquest cas TIPUSAVIO_ID).
L'etiqueta
indica que aquest identificador serà generat per Hibernate. Amb la directiva native indiquem que la generació d'aquest identificador es deixa en mans de la base de dades, que utilitzarà el mecanisme que utilitzi per defecte. Si vulguessim gestionar nosaltres la generació de l'identificador, hauriem d'indicar en l'atribut class la classe que se'n ocuparia.
Finalment, indiquem en quina columna de la taula on s'emmagatzemen els objectes d'aquesta classe s'han d'emmagatzemar cadascuna de les variables (nom i nombreSeients).

## Generació de l'esquema de la base de dades

Hibernate facilita una eina per a crear automàticament l'esquema de la classe persistent a la base de dades, utilitzant el fitxer de mapatge. D'aquesta forma evitem haver de fer-ho manualment.
Per a generar l'esquema haurem de:
* Crear un fitxer de configuració d'Hibernate, per a indicar-li els paràmetres de connexió a la base de dades
* Crear un fitxer de configuració d'Ant amb una tasca que genera l'esquema
Fitxer de configuració d'Hibernate (hibernate.properties):
Amb aquest fitxer informem a Hibernate sobre la ubicació de la base de dades que ha d'utilitzar, el llenguatge que ha de parlar amb aquesta base de dades, quin driver JDBC ha d'utilitzar i el nom d'usuari i contrasenya de connexió. Perquè Hibernate el trobi, s'ha de situar al directori executable de la nostra aplicació. En el nostre cas, el situarem al directori conf/ i utlitzarem Ant per a copiar-lo al directori build/classes cada cop que compilem.
Fitxer de configuració d'Ant (build.xml):
A partir d'aquest moment, quan vulguem generar l'esquema de la base de dades haurem d'executar:
a l'arrel del projecte o des de Eclipse.

## Emmagatzemament d'objectes

A continuació anem a veure un exemple de codi per a emmagatzemar objectes a la base de dades utilitzant Hibernate.
Cal resaltar que per a utilitzar Hibernate des d'Eclipse, cal afegir el seu .jar com a llibreria del projecte. Per a fer-ho, primer haurem d'instal·lar Hibernate al nostre disc dur.
Per a poder executar aquest codi utilitzant Ant, podem afegir les següents línies al fitxer build.xml:
Un cop afegides les línies, podrem executar el codi mitjançant Ant amb la comanda

## Recuperar dades

A continuació veiem un exemple de com recuperar les dades
Per a poder executar aquest codi utilitzant Ant, podem afegir les següents línies al fitxer build.xml:
Un cop afegides les línies, podrem executar el codi mitjançant Ant amb la comanda

# Proves unitàries
## Què són ?

Les proves unitàries, també anomenades proves d'objecte, son mètodes automatitzats de prova del funcionament d'un objecte de forma aïllada. Per implementar una prova unitària es crea una aplicació que fa crides als mètodes de l'objecte i compara els resultats obtinguts amb els desitjats.

## JUnit

JUnit és un conjunt d'utilitats que facilita la creació de proves unitàries d'aplicacions implementades amb Java.
Per a realitzar tests unitaris amb JUnit haurem de:
* Crear una classe que extengui a la classe TestCase
* Per a cada prova que vulguem realitzar, crearem un mètode amb un nom que comenci amb la paraula test seguida de qualsevol combinació de paraules
* Aquests mètodes no retornaran cap valor ni acceptaran paràmetres
* Dins d'aquests mètodes utilitzarem els mètodes assertXXX(objecte A, objecte B) de la classe TestCase, que retornen cert si els objectes A i B compleixen la propietat que dóna nom al mètode i fals en cas contrari. Per exemple, assertEquals("a","b") retornaria fals.
Quan executem aquesta classe com a test JUnit, aquest buscarà tots els mètodes amb nom començat per test i els executarà un a un, generant un informe dels mètodes que han fallat i els mètodes que no ho han fet.
Per a poder utilitzar Junit des d'Eclipse, haurem d'incloure el seu .jar com a llibreria del sistema. Per a fer-ho, en primer lloc haurem d'instal·lar Junit al nostre disc dur.
Veiem un exemple de prova unitària de la classe TipusAvio:
És important notar que les proves unitàries ens serveixen, a més de com a proves del bon funcionament d'un objecte, com a documentació del seu funcionament.

# Inversió de control
## Dependències

Les dependències entre classes es donen quan una classe utilitza una altra classe per a realitzar una determinada acció.

## Què és la inversió de control ?

La inversió de control és una tècnica que permet minimitzar les dependències entre classes en una aplicació. Per a fer-ho, aporta més control sobre aquestes dependències facilitant formes de configurar-les i canviar-les en temps d'execució.
La inversió de control requereix la utilització d'una tècnica anomenada Programació contra interfícies.

## Programació contra interfícies

S'anomena programació contra interfícies al fet de cridar als mètodes d'una interfície en comptes de fer-ho d'una classe concreta.
Exemple: Utilització de la interfície ResultSet de JDBC
En aquest codi, l'objecte ResultSet és en realitat una interfície. No sabem quina és la classe concreta que estem utilitzant per a realitzar les operacions. De fet, el mètode stmt.executeQuery podria retornar qualsevol classe que implementés la interfície ResultSet.
Ara suposem que volem implementar una classe per emmagatzemar les dades d'una aplicació.
Una primera aproximació seria fer-ho, com es mostra a l'exemple següent, creant una classe Persistencia que implementi un mètode guardarDades(Dades objecteDades).
L'aplicació hauria d'utilitzar aquesta classe de la forma que es mostra al programa
Utilitzar aquesta aproximació fa que únicament tinguem una manera d'emmagatzemar les dades de la nostra aplicació, tot i que sempre tindrem la possibilitat de canviar la implementació de la classe Persistencia per a canviar el seu comportament.
Però que passa si volem disposar de diverses formes d'emmagatzemar la informació i decidir quina utilitat en temps d'execució?
Aquest requisit s'anomena ampliació per connectors (plug-ins). L'aplicació facilita la implementació per defecte, a vegades buida, d'una funcionalitat, permet enganxar noves implementacions i escollir quina s'utilitza en temps d'execució, ja sigui mitjançant fitxers de configuració o a elecció de l'usuari.
Per a afegir aquest comportament a l'aplicació anterior, hauriem de transformar la classe Persistencia en una interficie, deixar que l'aplicació utilitzi aquesta interfície per a cridar al mètode guardarDades(Dades objecteDades), i facilitar-li una forma d'obtenir diverses implementacions de la interfície.
A continuació veiem la interfície Persistencia i dos implementacions diferents d'aquesta.

## Càrrega d'implementacions

Com fariem per a carregar una determinada implementació d'una interfície en l'exemple anterior ? Podem utilitzar una Factoria d'implementacions o la Inversió de control

### Factories d'implementacions

Per complertar la nostra aplicació, caldria escollir quina implementació de la interfície Persistencia utilitzem en cada moment. Utilitzant l'aproximació de la factoria d'implementacions, ho fariem de la forma que presentem a continuació:
La classe PersistenciaFactory serà l'encarregada de faciliar una implementació de la interfície Persistencia a l'aplicació. Al següent codi veiem un exemple de factoria que retorna sempre la mateixa implementació.
Una última millora seria que la factoria d'implementacions obtingués d'un fitxer de configuració el nom de la implementació a carregar, o que el prengués per paràmetre a l'operació getPersistencia. Veiem a continuació com es pot implementar aquest comportament

### Inversió de control

La inversió de control és una tècnica molt similar a una factoria d'implementacions que obté el nom de la implementació a carregar d'un fitxer de configuració. La única diferència és que a la classe que utilitza la interfície no li cal preocuparse de cridar a la factoria, és el propi sistema el que li facilita de forma automàtica la implementació configurada.

### Spring

Spring és un framework d'inversió de control per injecció de dependències. Facilita la obtenció d'implementacions eliminant tot el codi necessari per a fer-la dels objectes de les nostres aplicacions.
Exemple: Codi de la classe Aplicacio amb Spring
L'únic que cal fer per a configurar Spring és facilitar-li un fitxer de configuració que indiqui quina implementació de la interfície Persistencia utilitzarà la classe Aplicacio.
Exemple: Fitxer de configuració d'Spring
Ara, crearem una classe per a cridar a Aplicacio que serà la que farà ús d'Spring
Exemple: Classe CridaAplicacio, crida a l'aplicació injectant les dependències amb Spring