Je dobré pochopit potřebu objektového / relačního mapování (ORM) v aplikacích Java, ale pravděpodobně toužíte vidět Hibernate v akci. Začneme tím, že vám ukážeme jednoduchý příklad, který ukazuje část jeho síly.
Jak jistě víte, je běžné, že programovací kniha začíná příkladem „Hello World“. V této kapitole následujeme tuto tradici zavedením režimu spánku s relativně jednoduchým programem „Hello World“. Pouhý tisk zprávy do okna konzoly však nebude stačit k tomu, aby se režim Hibernace skutečně předvedl. Místo toho náš program uloží nově vytvořené objekty do databáze, aktualizuje je a provede dotazy k jejich načtení z databáze.
Kromě kanonického příkladu „Hello World“ představíme základní rozhraní Hibernate API a poskytneme podrobnosti základní konfigurace.
„Hello World“ s režimem spánku
Hibernační aplikace definují trvalé třídy, které jsou „mapovány“ na databázové tabulky. Náš příklad „Hello World“ sestává z jedné třídy a jednoho mapovacího souboru. Podívejme se, jak vypadá jednoduchá trvalá třída, jak je specifikováno mapování a některé věci, které můžeme dělat s instancemi trvalé třídy pomocí Hibernate.
Cílem naší ukázkové aplikace je ukládat zprávy do databáze a načítat je pro zobrazení. Aplikace má jednoduchou trvalou třídu, Zpráva
, což představuje tyto tisknutelné zprávy. Náš Zpráva
třída je uvedena v seznamu 1.
Výpis 1. Message.java: Jednoduchá trvalá třída
balíček ahoj; veřejná třída Zpráva {private Long id; soukromý text řetězce; soukromá zpráva nextMessage; private Message () {} public Message (String text) {this.text = text; } public Long getId () {return id; } private void setId (Long id) {this.id = id; } public String getText () {návratový text; } public void setText (text řetězce) {this.text = text; } veřejná zpráva getNextMessage () {návrat nextMessage; } public void setNextMessage (Zpráva nextMessage) {this.nextMessage = nextMessage; }}
Náš Zpráva
třída má tři atributy: atribut identifikátoru, text zprávy a odkaz na jiný Zpráva
. Atribut identifikátoru umožňuje aplikaci získat přístup k identitě databáze - hodnotě primárního klíče - trvalého objektu. Pokud dva případy Zpráva
mají stejnou hodnotu identifikátoru, představují stejný řádek v databázi. Vybrali jsme si Dlouho
pro typ našeho atributu identifikátoru, ale to není požadavek. Hibernace umožňuje pro typ identifikátoru prakticky cokoli, jak uvidíte později.
Možná jste si všimli, že všechny atributy Zpráva
třídy mají metody přístupového objektu ve stylu JavaBean. Třída má také konstruktor bez parametrů. Trvalé třídy, které používáme v našich příkladech, budou téměř vždy vypadat nějak takto.
Instance Zpráva
třída může být spravována (trvale) Hibernate, ale ne mít být. Protože Zpráva
objekt neimplementuje žádné Hibernate specifické třídy nebo rozhraní, můžeme jej použít jako jakoukoli jinou třídu Java:
Zpráva zpráva = nová zpráva („Hello World“); System.out.println (message.getText ());
Tento fragment kódu dělá přesně to, co jsme očekávali od aplikací „Hello World“: Vytiskne se "Ahoj světe"
do konzoly. Může to vypadat, že se tu snažíme být roztomilí; ve skutečnosti předvádíme důležitou vlastnost, která odlišuje Hibernate od některých dalších řešení perzistence, jako jsou fazole entit EJB (Enterprise JavaBean). Naše trvalou třídu lze použít v jakémkoli kontextu spuštění - není potřeba žádný speciální kontejner. Samozřejmě jste se sem přišli podívat na samotný Hibernate, tak si uložme nový Zpráva
do databáze:
Session session = getSessionFactory (). OpenSession (); Transakce tx = session.beginTransaction (); Zpráva zpráva = nová zpráva („Hello World“); session.save (zpráva); tx.commit (); session.close ();
Tento kód nazývá režim spánku Zasedání
a Transakce
rozhraní. (Dostaneme se k tomu getSessionFactory ()
zavolejte brzy.) Výsledkem je provedení něčeho podobného následujícímu SQL:
vložit do MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) hodnot (1, 'Hello World', null)
Vydrž - MESSAGE_ID
sloupec se inicializuje na podivnou hodnotu. Nenastavili jsme id
majetek zpráva
kdekoli, takže bychom očekávali, že to tak bude nula
, že jo? Vlastně id
vlastnost je speciální: Je to vlastnost identifikátoru—To obsahuje vygenerovanou jedinečnou hodnotu. (O tom, jak je hodnota generována, pojednáme později.) Hodnota je přiřazena k Zpráva
instance by Hibernate when Uložit()
je nazýván.
U tohoto příkladu předpokládáme, že ZPRÁVY
tabulka již existuje. Samozřejmě chceme, aby náš program „Hello World“ zprávu vytiskl na konzoli. Nyní, když máme zprávu v databázi, jsme připraveni to předvést. Následující příklad načte všechny zprávy z databáze v abecedním pořadí a vytiskne je:
Relace newSession = getSessionFactory (). OpenSession (); Transakce newTransaction = newSession.beginTransaction (); List messages = newSession.find ("from Message as m order by m.text asc"); System.out.println (messages.size () + "nalezené zprávy:"); for (Iterator iter = messages.iterator (); iter.hasNext ();) {Zpráva message = (Zpráva) iter.next (); System.out.println (message.getText ()); } newTransaction.commit (); newSession.close ();
Doslovný řetězec "ze zprávy jako m objednat podle m.text asc"
je dotaz Hibernate, vyjádřený ve vlastním objektově orientovaném Hibernate Query Language (HQL). Tento dotaz je interně přeložen do následujícího SQL, když nalézt()
je nazýván:
vyberte m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID z MESSAGES m pořadí podle m.MESSAGE_TEXT vzestupně
Fragment kódu vytiskne:
Nalezeno 1 zpráv: Hello World
Pokud jste nikdy předtím nepoužívali nástroj ORM, jako je Hibernate, pravděpodobně jste očekávali, že někde v kódu nebo metadatech uvidíte příkazy SQL. Nejsou tam. Veškerý SQL je generován za běhu (ve skutečnosti při spuštění, pro všechny opakovaně použitelné příkazy SQL).
Aby tato magie mohla nastat, potřebuje Hibernate více informací o tom, jak Zpráva
třída by měla být trvalá. Tyto informace jsou obvykle poskytovány v XML mapovací dokument. Mapovací dokument mimo jiné definuje, jak vlastnosti Zpráva
mapa třídy do sloupců ZPRÁVY
stůl. Podívejme se na mapovací dokument ve výpisu 2.
Výpis 2. Jednoduché mapování XML režimu spánku
Mapovací dokument říká Hibernate, že Zpráva
třída má být přetrvávána ZPRÁVY
tabulka, že vlastnost identifikátoru se mapuje na sloupec s názvem MESSAGE_ID
, že textová vlastnost se mapuje na sloupec s názvem MESSAGE_TEXT
, a že vlastnost s názvem další zpráva
je sdružení s multiplicita více ku jedné který se mapuje na sloupec s názvem NEXT_MESSAGE_ID
. (O další podrobnosti se zatím nebojte.)
Jak vidíte, dokument XML není těžké pochopit. Můžete jej snadno psát a udržovat ručně. Bez ohledu na to, jakou metodu zvolíte, Hibernate má dostatek informací k úplnému vygenerování všech příkazů SQL, které by byly potřeba k vložení, aktualizaci, odstranění a načtení instancí Zpráva
třída. Tyto příkazy SQL již nemusíte psát ručně.
Poznámka |
---|
Mnoho vývojářů Java si stěžovalo na „peklo metadat“, které doprovází vývoj J2EE. Někteří navrhli odklon od metadat XML zpět k prostému kódu Java. Ačkoli tomuto návrhu tleskáme u některých problémů, ORM představuje případ, kdy jsou textová metadata skutečně nezbytná. Hibernate má rozumná výchozí nastavení, která minimalizují psaní a definici vyspělého typu dokumentu, kterou lze použít k automatickému dokončení nebo ověření v editorech. Můžete dokonce automaticky generovat metadata pomocí různých nástrojů. |
Pojďme nyní změnit naši první zprávu a když už jsme u toho, vytvořme novou zprávu spojenou s první, jak je uvedeno v Seznamu 3.
Výpis 3. Aktualizace zprávy
Session session = getSessionFactory (). OpenSession (); Transakce tx = session.beginTransaction (); // 1 je vygenerované ID první zprávy Message message = (Message) session.load (Message.class, new Long (1)); message.setText ("Pozdrav Pozemšťan"); Zpráva nextMessage = nová zpráva („Vezměte mě za svým vůdcem (prosím)“); message.setNextMessage (nextMessage); tx.commit (); session.close ();
Tento kód volá tři příkazy SQL uvnitř stejné transakce:
vyberte m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID z MESSAGES m, kde m.MESSAGE_ID = 1 vložit do MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) hodnot (2, 'Take me to your leader (please)', null) aktualizovat MESSAGES set MESSAGE_TEXT = 'Zdravím Pozemšťana', NEXT_MESSAGE_ID = 2 kde MESSAGE_ID = 1
Všimněte si, jak Hibernate detekoval modifikaci text
a další zpráva
vlastnosti první zprávy a automaticky aktualizoval databázi. Využili jsme funkci Hibernate s názvem automatická kontrola znečištění: tato funkce nám ušetří námahu výslovně požádat Hibernate o aktualizaci databáze, když upravíme stav objektu uvnitř transakce. Podobně můžete vidět, že nová zpráva byla trvalé, když byl vytvořen odkaz z první zprávy. Tato funkce se nazývá kaskádové uložení: to nám ušetří námahu explicitně učinit nový objekt trvalým voláním Uložit()
, pokud je dosažitelný již trvalou instancí. Všimněte si také, že pořadí příkazů SQL není stejné jako pořadí, ve kterém nastavujeme hodnoty vlastností. Režim spánku používá sofistikovaný algoritmus k určení efektivního řazení, které se vyhne narušení omezení cizího klíče databáze, ale je pro uživatele stále dostatečně předvídatelné. Tato funkce se nazývá transakční zápis.
Pokud znovu spustíme program „Hello World“, vytiskne se:
Nalezeno 2 zpráv: Pozdrav Pozemšťan Vezměte mě ke svému vůdci (prosím)
To je, pokud vezmeme aplikaci „Hello World“. Nyní, když konečně máme nějaký kód pod opaskem, uděláme krok zpět a představíme přehled hlavních rozhraní API Hibernate.
Porozumění architektuře
Programovací rozhraní jsou první věcí, kterou se musíte o Hibernate naučit, abyste jej mohli použít ve vrstvě perzistence vaší aplikace. Hlavním cílem designu API je udržovat rozhraní mezi softwarovými komponentami co nejužší. V praxi však rozhraní ORM API nejsou nijak zvlášť malá. Nebojte se; nemusíte rozumět všem rozhraním Hibernate najednou. Obrázek níže ilustruje role nejdůležitějších rozhraní Hibernate ve vrstvách podnikání a perzistence.
Ukážeme obchodní vrstvu nad vrstvou perzistence, protože vrstva obchodní funguje jako klient vrstvy perzistence v tradičně vrstvené aplikaci. Všimněte si, že některé jednoduché aplikace nemusí čistě oddělit obchodní logiku od logiky vytrvalosti; to je v pořádku - pouze to zjednodušuje diagram.
Rozhraní režimu spánku uvedená na obrázku výše lze přibližně klasifikovat takto:
- Rozhraní volaná aplikacemi k provádění základních operací CRUD (vytváření / čtení / aktualizace / mazání) a dotazování. Tato rozhraní jsou hlavním bodem závislosti aplikační obchodní / řídicí logiky na režimu spánku. Obsahují
Zasedání
,Transakce
, aDotaz
. - Rozhraní volaná kódem aplikační infrastruktury pro konfiguraci Hibernate, nejdůležitější je
Konfigurace
třída. - Zpětné volání rozhraní, která umožňují aplikaci reagovat na události vyskytující se uvnitř režimu spánku, jako je
Interceptor
,Životní cyklus
, aPlatné
. - Rozhraní, která umožňují rozšíření výkonné funkce mapování Hibernate, jako je
UserType
,CompositeUserType
, aIdentifikátorGenerátor
. Tato rozhraní jsou implementována kódem aplikační infrastruktury (je-li to nutné).
Hibernate využívá stávající rozhraní Java API, včetně JDBC (Java Database Connectivity), Java Transaction API (JTA) a Java Naming and Directory Interface (JNDI). JDBC poskytuje základní úroveň abstrakce funkcí společných pro relační databáze, což umožňuje téměř jakoukoli databázi s ovladačem JDBC podporovat režim Hibernate. JNDI a JTA umožňují integraci Hibernate s aplikačními servery J2EE.
V této části se nezabýváme podrobnou sémantikou metod rozhraní Hibernate API, pouze rolí každého z primárních rozhraní. Většinu těchto rozhraní najdete v balíčku net.sf. zimovat
. Pojďme se postupně krátce podívat na každé rozhraní.
Základní rozhraní
Pět základních rozhraní se používá téměř v každé aplikaci Hibernate. Pomocí těchto rozhraní můžete ukládat a načítat trvalé objekty a řídit transakce.
Rozhraní relace