Programování

Začněte s Hibernate

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, a Dotaz.
  • 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, a Platné.
  • Rozhraní, která umožňují rozšíření výkonné funkce mapování Hibernate, jako je UserType, CompositeUserType, a Identifiká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

$config[zx-auto] not found$config[zx-overlay] not found