Tipy a triky
05.02.2019
Skillmea
Java persistence – JPA, Hibernate, ORM
JPA je java persistence api specifikace. K tomu, abys mohl používat JPA ve skutečné aplikaci, potřebuješ implementaci JPA. Buď použiješ servery, které již nabízejí implementaci JPA, jako například GlassFish, nebo použiješ implementaci, kterou ti poskytuje framework Hibernate nebo EclipseLink.
Pokud používáme JPA standardy, tak je v budoucnu úplně jedno, jakou implementaci JPA budeme používat. Při programování budeme používat JPA anotace, které pocházejí z balíku javax.persistence. V budoucnu můžeš nasadit aplikaci na GlassFish, který zná javax.persistence a umí s tím pracovat nebo na Tomcat s použitím Hibernate, který také zná javax.persistence a umí s tím pracovat.
Co je Persistence?Pokud vytvoříš ledajaký jednoduchý objekt, co se stane? Například objekt Adresa? Vytvoří se v haldě – v paměti. Objekt může mít nasetována nějaká data – informace. Pokud se ale ztratí reference v javovském kódu na tento objekt v haldě - tak se smaže.
Pokud si chceme uchovat tyto informace, tak je můžeme uložit do databáze a nejlépe, aby po vytažení z databáze měla tato data stejnou formu – tedy formu objektu Adresa.
Tomu se říká, že persistujeme (uchováme stálost) objekt do databáze. Jako by tento objekt existoval i mimo java programu. Tento objekt se uchová v úložišti a znovu se vytvoří, bude-li třeba.
Co je ORM?Klasické databáze jako Oracle, MySql a podobně jsou relační databáze, které mají data uložena ve formě tabulek. V jevu ukládáme data ve formě objektů, v databázi ve formě tabulek. Ale co mají podobné? V relační databázi máme sloupce, které mají názvy a v řádcích máme hodnoty. Něco jako klíč hodnota – totéž platí i pro objekty v jevu – tam máme název proměnné a hodnotu v ní uloženou.
Tady přichází pod ruku ORM – tedy object relational mapping. Je to něco jako objektově relační mapování. My naše java objekty namapujeme na tabulky relační databáze. Abychom věděli, že toto pole v javovském objektu patří do tohoto sloupce.
Objekty v jevu jsou mezi sebou propojeny pomocí uložení reference na daný objekt. Například člověk má field Adresa, kde je uložena reference na objekt Adresa.
Relační tabulky mají mezi sebou také vazby. Buď máme v tabulce pro člověka sloupec adresa, kde bude uložen identifikátor adresy a na základě tohoto identifikátoru najdeme danou adresu. Nebo existuje speciální tabulka, kde budou dva sloupce jeden pro identifikátor adresy a druhý pro identifikátor člověka. My pak umíme najít, jaké adresy má člověk nastaveno, nebo pro jakého člověka je nastavena daná adresa.
[Image]
Problém s JDBC přístupem – výhoda ORMV kurzu Java pro pokročilé , pokud jsi tento kurz viděl, jsme si ukazovali přístup k databázi přes JDBC. Co jsme udělali? Otevřeli jsme konekci na databázi, napsali jsme sql příkaz, který jsme následně poslali do databáze k provedení. Databáze nám vrátila výsledek ve formě result setu.
Představ si, že máš jen 5 až 10 tabulek. Nad každou tabulkou máš například 4 různé sql příkazy - to máme přibližně 20 - 40 sql příkazů. Pokud se ti stane, že musíš změnit databázi – například změníš název sloupce v tabulce? Co musíš udělat? Musíš přepsat název tohoto sloupce na xy místech – na 20 až 40 místech – a to jsme jen v malé aplikaci – co kdyby to bylo na 100 místech?.
Byl by v tom nepořádek a mohly by nastat problémy.
Pokud ale použijeme ORM, tak v jevu pracujeme s naším kódem, tak jako běžně. Vytvoříme si objekty typu Clovek, nastavíme mu nějaké hodnoty. Dále si vytvoříme kolekci adres pro daného člověka. Nakonec v ORM frameworku řekneme jen persistní mi tento objekt. ORM se pak postará o veškeré uložení těchto objektů do databáze na základě mapování, které mu poskytneme.
Clovek clovek = new Clovek();
clovek.setMeno("Jaro");
clovek.setPriezvisko("Beno");
Adresa adresa1 = new Adresa();
adresa1.setUlica("Nejaka 5");
adresa1.setPSC("94404");
Adresa adresa2 = new Adresa();
adresa2 = new Adresa();
adresa2.setUlica("Nejaka 5");
adresa2.setPSC("94404");
List<Adresa> adresaList = Arrays.asList(adresa1, adresa2);
clovek.setAdresaList(adresaList);
orm.persist(clovek);
Pokud bychom nepoužili ORM, sami bychom museli napsat metodu, která nám otevře konekci na databázi, museli bychom napsat INSERT SQL příkaz pro člověka a poté i pro jeho adresy a museli bychom zajistit, abychom nastavili všude data tam, kde mají být a musíme se postarat io propojení mezi těmito dvěma objekty.
Pokud ale použijeme ORM, tak se nemusíme starat o tento balast kódu, ale soustředit se zejména na to, co prodává a to je business logika aplikace.
Nevýhody JDBC přístupu jsou tedy, že máme příliš mnoho SQL příkazů, velmi mnoho kopie kódu, ručně se musíme postarat o nastavení dat do správných sloupců.
Výhodou ORM je, že nemusíme dělat tyto věci z předchozí věty. ORM nám umožní používat java objekty k reprezentaci relační databáze. ORM se nám postará io propojení závislostí. ORM spojí výhody relační databáze a objektového modelu v jevu plus schová veškerou komplexitu SQL příkazů.
Co je Hibernate?Hibernate je ORM – object relational mapping framework, který slouží k mapování java objektů na tabulky relačních databází.
Java programátoři jsou zvyklí psát kód v objektech, proč tedy potřebují další jazyk – sql – k získání dat z databáze? Hibernate na pozadí sám vytváří sql příkazy nad databází a proto nemusíme psát sql příkazy my.
Pokud chceme uložit mapu objektů, například Cloveka, který má Adresu, nebo i více objektů typu Adres, tak nemusíme psát všechny sql příkazy. Stačí, když zavoláme jednoduchou metodu pro uložení objektu do databáze a hibernate se postará o zbytek.
Hibernate je také implementace JPA.
[Image]
Co je JPA?Zkratka JPA je Java Persistence API. Co to znamená? V jednoduchosti řečeno - je to standard. Poněkud složitěji řečeno – je to specifikace pro OR mapování a je součástí Java EE, ale můžeme ji používat i v Java SE projektech.
Některé servery poskytují vlastní implementaci JPA a některé ne – v tom případě použijeme například Hibernate implementaci.
Představ si, že celý tvůj kód používá věci z JPA. Nyní je na tobě, kam nasadíš svoji aplikaci. Pokud ji nasadíš na Glassfish nemusíš předělávat svůj kód, který používá JPA – Glassfish ho zná. Pokud svou aplikaci nasadíš na Tomcat, tak mu přihodíš Hibernate, který také zná JPA. Potom tvůj kód bude fungovat všude – neboť používá standardy JPA.
Je možné, abychom používali jen Hibernate – tedy bychom nepoužívali nic ze standardů. Žádné anotace z javax.persistence a podobně – to ale nedoporučuji.
Ptal jsem seNapadlo mě, že by nebylo od věci zeptat se kolegů developerů, co si myslí o JPA a Hibernatě. Pokud by sis chtěl přečíst jejich názory, ať se líbí – bez cenzury, cituji:
Tak toto je náročné téma a navíc složité.
JPA resp. ORM obecně (a tedy i Hibernate) jsou vždy složitější, než si uživatelé (tj. vývojáři) uvědomují. Výsledkem jsou často nenápadné chybičky, lazy load exceptions, které vedou k anti-patternům jako je OSIV (open session in view) nebo k výkonovým problémům (n+1 problem).
Těchto problémů je typicky o to více, o co složitější je mapování – a přitom právě na řešení složitého mapování bylo ORM vymyšleno. Abychom mohli namapovat doménu do DB. K tomu se často používají i „mimojazykové“ triky jako reflection na private pole, takže objekty jsou implicitně svázány s ORM řešením, i když například. mapování je odděleno do XML namísto anotací, což samo o sobě je také nepraktické.
Kromě toho mají obě hlavně implementace dost bugů na to, aby na ně člověk narazil, i když postupuje v souladu se specifikací – stačí jen chtít trosku víc a na nějaký bug určitě narazíte. Takže pak to je kličkování mezi bugy a často komplikovaná možnost vyměnit ORM providera.
Co se mi na ORM líbí je lepší mapování typů, možnost customizovat mapování a podobně. Proto používám JPA i na jednoduché mapovačky namísto JDBC.
Navíc s JPA používám řadu Querydsl, které je lepší/intuitivnější, než JPA standardní Criteria API.
Hibernate používám dlouho ale po pravdě řečeno nikdy jsem se moc nezamýšlel nad výhodami. Zatím jsem neměl výraznější problém, který bych neuměl vyřešit, případně nějak obejít.
Plusy :
- snadno se provádí mapování do DB s anotacemi i pro začátečníka bez velkých znalostí databáze, zároveň ale bez znalosti DB může být mapování neefektivní
- je open source, takže pokud potřebuji, umím podívat zdrojáky jak funguje
Minusy :
- asociace OneToOne fetch=lazy nefunguje
Na používání Hibernate/JPA (celkově ORM vrstvě) se mi líbí :
A) Abstrakce od fyzického datového modelu. Vývoj nad doménovým/logickým (entitně-relačním datovým modelem) - blíže k byznys vrstvě. Čili zjednodušené práce s objekty namísto tabulek.
B) Možnost využívat různé pokročilejší techniky získávání dat (např. Spring Data JPA, ale také zjednodušující Hibernate Query by example)
C) Agnostické od konkrétní databázové technologie (Oracle, MySql, ...)
D) Cachování a optimalizace (např. lazy loading)
Nevýhody :
A) Někdy náročný (až nemožný) performance tuning.
B) U některých technologií pomalejší křivka učení.
C) I přes používání JPA/Hibernate, je téměř nezbytné, aby developer znal i (native) SQL jazyk a jeho použití.
ZávěrPodařilo se ti nahlédnout do problematiky objektově relačního přístupu k databázi a pochopil jsi, co to znamená. Pokud se však chceš dostat ještě o level dál, připravili jsme pro tebe samostatný kurz Java persistence - JPA a Hibernate .
Pokud chceš ještě víc, tak klikej:👍 Více o mně: http://www.jaroslavbeno.cz/ 👍 Kurzy (java, git, maven, bootstrap, Asp .Net,): Learn2Code moje kurzy 👍 Free kurzy: YouTube kanál JaroslavBeno