ORM je skratka výrazu Object-Relation Mapping, čo je princíp toho, že sa údaje uložené v relačnej databáze namapujú na objekty v pamäti alebo naopak. Je to často dôležitý premosťovací prvok medzi týmito dvoma svetmi, ktoré si nemusia byť vždy až tak blízke a niekedy veľká pomôcka pre programátorov, ktorí majú zrazu databázové údaje v kolekciách objektov. Aj preto JavaEE neostala tejto téme veľa dlžná a obsahuje špecifikáciu s názvom Java Persistent API (alebo JPA), ktorá popisuje implementáciu takého mapovania.
Ak ste sa niekedy dostali prvýkrát k ORM mapovaniu, mohlo vám to pripadať celkom jednoduché. V databáze je tabuľka, ktorá ma napríklad päť stĺpcov. V kóde mám zadefinovaný objekt, ktorý má päť vlastností (vnútorných premenných) a ORM vrstva sa postará, aby ste údaje z tej tabuľky dostali do objektu. A to by mohlo byť všetko, ale nie je. Určite nie v prípade JPA. ORM je v tejto špecifikácii živá vrstva vašej aplikácie, ktorej schopnosť robiť toto mapovanie je hlavnou, ale nie jedinou funkciou. Poďme ale pekne po poriadku, najprv úplné základy
Všetko je to tom, ako som napísal vyššie, že potrebujete tabuľku a potrebujete triedu. Trieda je tzv. POJO (Plain Old Java Object), čo znamená, že nemusí implementovať nejaké rozhranie alebo byť odvodená od inej, špeciálnej triedy z JPA. Stále ale nejako potrebujete povedať, ako bude prebiehať mapovanie a na to máte dve možnosti: anotácie alebo xml súbor. Anotácie umiestnite priamo do triedy – napríklad anotáciu @Entity použijete na triedu a v nej uvediete názov tabuľky, na ktorú bude trieda mapovaná. Potom aj k jednotlivým vlastnostiam triedy viete doplniť anotácie, aby bolo jasné, na ktorý stĺpec v databáze sa daná vlastnosť mapuje. Tieto druhé anotácie už ale nie sú povinné a môžete ich vynechať, ak sa názov vlastnosti zhoduje s názvom stĺpca. Xml súbor môže byť, ako aj iné JavaEE descriptory, pribalený v správnom priečinku v .war alebo .ear súbore. A popisuje to isté, ale svojím – xml – štýlom. Treba povedať, že XML má vyššiu prioritu ako anotácie, teda ak sú zadefinované obe, a protirečia si, tak sa použije to, čo je v XML súbore. Je to preto, aby človek, ktorý sa stará o deployment, a je si vedomý produkčného prostredia, do ktorého aplikácia ide, bol schopný niektoré veci ovplyvniť.
Ak sa bavíme o JPA, treba si uvedomiť, že tu hovoríme hlavne o vrstve objektového modelu, ktorý sa mapuje na databázu a naopak. A treba dodať, že to mapovanie medzi databázou a týmto modelom vôbec nemusí byť jedna k jednej, ako som popísal vyššie, ale môžu byť medzi nimi aj veľké rozdiely, ktoré je ale JPA schopné prekonať rôznymi nástrojmi, ktorými má (napríklad mapovanie viacerých objektov na jednu tabuľku alebo naopak). Teda nepracujete tu (alebo presnejšie povedané nemusíte pracovať) s obrazom databázy v pamäti, ale s vlastným objektovým modelom, ktorý sa aj viac riadi možnosťami objektov (napríklad dedenie, ktoré v svete relačných databáz neexistuje). Druhú vec, ktorú si musíte uvedomiť, že JPA nie je mŕtva vrstva, ktorá len raz za čas presype údaje z pamäti do databázy ale naopak. Je to naopak, celkom živá vrstva, ktorá spolupracuje so svojím okolím a v ktorej majú napríklad objekty svoj vlastný životný cyklus.
Tak v prvom rade sa pri mapovaní v pamäti vytvorí tzv. persistent context. To je niečo, ako miesto v pamäti, do ktorého sa načítavajú jednotlivé objekty z databázy (resp. sa do neho dostanú nové objekty, pred tým než sa databázy uložia). Aby sa niečo také vytvorilo, je potrebné mať zadefinované persistence unit, čo je XML súbor popisujúci pripojenie na databázu a tiež definuje, kde v balíku sa nachádzajú súbory s triedami entít (len dodám, že je to iný XML súbor ako ten s mapovaním, ktorý som spomínal vyššie). Tento persistent context funguje tak trochu magicky, pretože napríklad objekt, ktorý je v ňom načítaný, stačí modifikovať a bez nejaký ďalších príkazov sa zmena sama automaticky uloží do databázy. Všetky objekty, ktoré majú byť pridané do databázy musia byť najprv pridané do tohto persistent contextu a až odtiaľ potom do databázy, atď. API na manipuláciu s objektami a tiež s persistent contextom predstavuje trieda EntityManager, ktorej inštancia sa získava práve pre nejakú konkrétnu persistent unit.
JPA je (ako to býva u JavaEE špecifikácií zvykom) určitým spôsobom prepojená s ostatnými špecifikáciami. A tak sa napríklad persistent context môže správať inak, podľa toho či je EntityManager používaný v Stateless alebo Statefull EJB. Alebo je prepojený na JTA a tá synchronizácia s databázou prebieha pri commite transakcie. V skutočnosti exituje viacero variant, ako sa persistent context môže správať (dané prostredím, do ktorého je nasadený alebo priamo nejakým príkazom API). Na začiatku je ale veľmi pravdepodobné, že vám budú vyhovovať default nastavenia.
Pre relačné databázy je prvoradým jazykom štandard SQL. Pre JPA to tak nie je, aj keď z možností, ako robiť dotazy, zahŕňa aj SQL. Tu sú všetky spôsoby, ako viete dotazovať (a hromadne aktualizovať) objekty:
1. JPQL – Java Persistent Query Language – niečo ako SQL, ale dotaz sa nedeje nad relačnou databázou ale nad objektovým modelom
2. Weak Typed Criteria API – dotaz sa vytvorí komplet cez objektové API, kde vytváraním objektov a volaním metód postupne zadefinujete všetky časti dotazu. Weak Typed preto, lebo sa nijako nerozpoznávaju ani nekontrolujú typy stĺpcov a hodnôt v podmienkach a pod.
3. Strong Types Criteria API – dotaz sa podobne ako v predchádzajúcom prípade vyskladáva čiste procedurálnou cestou, ale tentokrát sa to deje tak, že sa kontrolujú aj jednotlivé typy údajov, ktoré sa v dotaze používajú.
4. Named Queries – ako názov napovedá, ide o dotazy, ktoré sú pomenované. Tieto dotazy sú väčšinou definované priamo v entite a sú buď napísané v JPQL alebo v SQL. Pomocou ich mena je možné ich volať a tak získať výsledok.
To všetko je len stručný prehľad a ani ten nie je úplný. JPA obsahuje ďalšie témy, ako sú napríklad lifecycle events (je možné zadefinovať metódy, ktoré sú volané pri určitých udalostiach, ktoré sa dejú s Entitou), validáciu (prepojenie na javax.validation), caching, locking alebo riešenie konkurenčného prístupu. Ďalej obsahuje možnosti a nastavenie pre Lazy načítanie údajov (predstavte si, že sa Entita vyčíta z databázy, ale niektorá jej vlastnosť sa reálne načíta do pamäte až keď je prvýkrát vyžiadaná) alebo generovanie schémy databázy na základe objektového modelu.
O tom, že JPA nie je malá téma, svedčí aj to, že sa o ňom dá napísať 497-stranová kniha a to konkrétne Pro JPA 2 od Mika Keitha a Merricka Schincariola. Tento kúsok sa mi dostal do rúk a vďaka nemu som zistil, že JPA nie je len jednoduchý automat, ktorý vám vie dáta z databázy preniesť do objektovej štruktúry v pamäti a naopak. Knihu vám odporúčam, ak už viete programovať v Jave a viete aspoň zhruba, čo to JavaEE je, a aj v prípade, že už máte nejaké skúsenosti s JPA. Ak ste s ním nerobili veľmi obšírne na rôznych projektoch, je veľmi pravdepodobné, že má svoje zákutia, o ktorých ani neviete. Autori zvolili komplexný prístup, a tak sa začína dokonca ľahším vysvetlím, či je Enterprise aplikácia, následne čo je to ORM a potom už jedna téma za druhou od tých jednoduchších ako je obyčajné oanotovanie triedy entity až po veci ako sú entitné grafy (čo je pomerne zložitý spôsob, ako mapovať rôzne objetkové modely s rôznou požiadavkou na Lazy/Eager dostupnosť údajov na tú istú relačnú štruktúru – téma, ktorá by si zaslúžila článok sám o sebe). Preto, ak sa chcete dozvedieť, čo to JPA je, alebo aj v prípade, že už anotujete entity, ale chcete vedieť čo sa ešte viac dá s JPA robiť, vám knihu odporúčam.