Výukový program pre hibernáciu jednej z mnohých poznámok
1. Úvod
Tento rýchly výukový program Hibernate nás prevedie príkladom a jedna k mnohým mapovanie pomocou anotácií JPA, alternatíva k XML.
Dozvieme sa tiež, čo sú obojsmerné vzťahy, ako môžu vytvárať nezrovnalosti a ako môže pomôcť myšlienka vlastníctva.
2. Opis
Jednoducho povedané,jedna k mnohým mapovanie znamená, že jeden riadok v tabuľke je namapovaný na viac riadkov v inej tabuľke.
Pozrime sa na nasledujúci diagram vzťahov entít, aby sme videli a jedna k mnohým združenie:

V tomto príklade implementujeme systém košíkov, kde máme tabuľku pre každý košík a ďalšiu tabuľku pre každú položku. Jeden košík môže obsahovať veľa položiek, takže tu máme jedna k mnohým mapovanie.
Na úrovni databázy to funguje tak, že máme a cart_id ako primárny kľúč v vozík stôl a tiež a cart_id ako cudzí kľúč v položky.
V kóde to robíme takto @OneToMany.
Poďme zmapovať Košík triedy do Položky objekt spôsobom, ktorý odráža vzťah v databáze:
public class Cart {// ... @OneToMany (mappedBy = "cart") súkromné položky sady; // ...}
Môžeme tiež pridať odkaz na Košík v Položky použitím @ManyToOne, čo z neho robí obojsmerný vzťah. Obousmerný to znamená máme prístup položky od vozíky, a tiež vozíky od položky.
The mappedBy property je to, čo používame na to, aby sme Hibernate povedali, ktorú premennú používame na reprezentáciu rodičovskej triedy v našej podradenej triede.
Nasledujúce technológie a knižnice sa používajú na vývoj vzorovej aplikácie Hibernate, ktorá sa implementuje jedna k mnohým združenie:
- JDK 1,8 alebo novší
- Hibernácia 5
- Maven 3 alebo novší
- Databáza H2
3. Inštalácia
3.1. Nastavenie databázy
Nižšie je uvedený náš databázový skript pre Košík a Položky stoly. Používame obmedzenie cudzieho kľúča pre jedna k mnohým mapovanie:
CREATE TABLE `Cart` (` cart_id` int (11) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`cart_id`)) ENGINE = InnoDB AUTO_INCREMENT = 5 DEFAULT CHARSET = utf8; CREATE TABLE `Items` (` id` int (11) unsigned NOT NULL AUTO_INCREMENT, `cart_id` int (11) unsigned NOT NULL, PRIMARY KEY (` id`), KEY `cart_id` (` cart_id`), CONSTRAINT `items_ibfk_1 `ZAHRANIČNÝ KLÍČ (` cart_id`) REFERENCIE `Cart` (` cart_id`)) ENGINE = InnoDB AUTO_INCREMENT = 7 VÝCHOZÍ CHARSET = utf8;
Naše nastavenie databázy je pripravené, takže poďme k vytvoreniu ukážkového projektu dlhodobého spánku.
3.2. Maven závislosti
Potom do nášho systému pridáme závislosti ovládačov Hibernate a H2 pom.xml spis. Závislosť režimu dlhodobého spánku používa protokolovanie JBoss a automaticky sa pridáva ako prechodné závislosti:
- Hibernácia verzie 5.2.7. Konečné
- Ovládač H2 verzia 1.4.197
Najnovšie verzie Hibernate a závislostí H2 nájdete v centrálnom úložisku Maven.
3.3. Konfigurácia dlhodobého spánku
Tu je konfigurácia režimu dlhodobého spánku:
org.h2.Driver jdbc: h2: mem: spring_hibernate_one_to_many sa org.hibernate.dialect.H2Dialect vlákno true
3.4. HibernateAnnotationUtil Trieda
Vďaka HibernateAnnotationUtil triedy, stačí odkázať na nový konfiguračný súbor režimu dlhodobého spánku:
private static SessionFactory sessionFactory; private SessionFactory buildSessionFactory () {ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder (). configure ("hibernate-annotation.cfg.xml"). build (); Metadata metadata = new MetadataSources (serviceRegistry) .getMetadataBuilder (). Build (); SessionFactory sessionFactory = metadata.getSessionFactoryBuilder (). Build (); návrat sessionFactory; } public SessionFactory getSessionFactory () {if (sessionFactory == null) sessionFactory = buildSessionFactory (); návrat sessionFactory; }
4. Modely
Konfigurácie súvisiace s mapovaním sa uskutočnia pomocou anotácií JPA v modelových triedach:
@Entity @Table (name = "CART") verejná trieda Cart {// ... @OneToMany (mappedBy = "cart") súkromné položky sady; // zakladatelia a zakladatelia}
Upozorňujeme, že @OneToMany anotácia sa používa na definovanie vlastnosti v Položky triedy, ktorá sa použije na mapovanie mappedBy premenná. Preto máme nehnuteľnosť s názvom „vozík“V Položky trieda:
@Entity @Table (name = "ITEMS") položky verejnej triedy {// ... @ManyToOne @JoinColumn (name = "cart_id", nullable = false) súkromný košík; public Items () {} // getters and setters}
Je tiež dôležité poznamenať, že @ManyToOne anotácia je spojená s Košík premenná triedy. @JoinColumn anotácia odkazuje na mapovaný stĺpec.
5. V akcii
V testovacom programe vytvárame triedu s a hlavný() metóda na získanie relácie dlhodobého spánku a uloženie modelových objektov do databázy implementujúcej jedna k mnohým združenie:
sessionFactory = HibernateAnnotationUtil.getSessionFactory (); session = sessionFactory.getCurrentSession (); System.out.println ("Relácia vytvorená"); tx = session.beginTransaction (); session.save (košík); session.save (položka1); session.save (item2); tx.commit (); System.out.println ("Cartitem1, cudzí kľúč Cartitem2, cudzí kľúč Cartmany-to-one">6. @ManyToOne AnotáciaAko sme videli v časti 2, môžeme určiť a mnoho-k-jednému vzťah pomocou @ManyToOne anotácia. A mnoho-k-jednému mapovanie znamená, že veľa inštancií tejto entity je mapovaných na jednu inštanciu inej entity - veľa položiek v jednom košíku.
The @ManyToOne anotácia nám umožňuje vytvárať aj obojsmerné vzťahy. Tomu sa budeme podrobne venovať v niekoľkých nasledujúcich pododdieloch.
6.1. Nezrovnalosti a vlastníctvo
Teraz, ak Košík odkazované Položky, ale Položky nemal zase odkaz Košík, náš vzťah by bol jednosmerný. Predmety by mali tiež prirodzenú konzistenciu.
V našom prípade je však vzťah obojsmerný, zavedenie možnosti nekonzistencie.
Poďme si predstaviť situáciu, keď chce vývojár pridať položka1 do vozík a položka2 do košík2, ale robí chybu tak, že odkazy medzi košík2 a položka2 sa stanú nekonzistentnými:
Cart cart1 = nový košík (); Cart cart2 = nový košík (); Položky item1 = nové položky (cart1); Položky item2 = nové položky (cart2); Set itemsSet = new HashSet (); itemsSet.add (item1); itemsSet.add (item2); cart1.setItems (itemsSet); // zle!
Ako je uvedené vyššie, položka2 referencie cart2, keďže košík2 neodkazuje item2, a to je zlé.
Ako by mal režim dlhodobého spánku šetriť položka2 do databázy? Will položka2 odkaz na cudzí kľúč košík1 alebo košík2?
Túto nejednoznačnosť riešime pomocou myšlienky vlastniť stranu vzťahu; odkazy patriace vlastniacej strane majú prednosť a ukladajú sa do databázy.
6.2. Položky ako strana vlastniaca
Ako je uvedené v špecifikácii JPA v časti 2.9, je dobrým zvykom známkovať mnoho-k-jednému strana ako strana vlastniaca.
Inými slovami, Jatems by bola vlastniacou stranou a Košík inverzná strana, čo je presne to, čo sme urobili predtým.
Ako sme to teda dosiahli?
Zahrnutím mappedBy atribút v Košík triedy, označíme ako inverznú stranu.
Zároveň tiež anotujeme Položky.vozík pole s @ManyToOne, výroba Položky vlastniaca strana.
Keď sa vrátime k nášmu príkladu „nekonzistencie“, Hibernate teraz vie, že položka2Odkaz je dôležitejší a ušetrí položka2Odkaz na databázu.
Poďme skontrolovať výsledok:
item1 ID = 1, ID košíka s cudzím kľúčom = 1 item2 ID = 2, ID košíka s cudzím kľúčom = 2
Hoci vozík referencie položka2 v našom úryvku, položka2Odkaz na košík2 je uložený v databáze.
6.3. Košík ako strana vlastniaca
Je tiež možné označiť jedna k mnohým strana ako strana vlastniaca a - mnoho-k-jednému strana ako inverzná strana.
Aj keď to nie je odporúčaná prax, poďme to skúsiť.
Fragment kódu nižšie ukazuje implementáciu jedna k mnohým strana ako strana vlastniaca:
verejná trieda ItemsOIO {// ... @ManyToOne @JoinColumn (name = "cart_id", insertable = false, updatable = false) súkromný košík CartOIO; // ..} verejná trieda CartOIO {// .. @OneToMany @JoinColumn (name = "cart_id") // musíme duplikovať fyzické informácie súkromné položky Set; // ..}
Všimnite si, ako sme odstránili mappedBy prvok a nastavte mnoho-na-jeden @ JoinColumn ako vložiteľný a aktualizovateľné do nepravdivé.
Ak spustíme rovnaký kód, bude výsledok opačný:
item1 ID = 1, ID košíka s cudzím kľúčom = 1 item2 ID = 2, ID košíka s cudzím kľúčom = 1
Ako je uvedené vyššie, teraz položka2 patrí vozík.
7. Záver
Videli sme, aké ľahké je implementovať jedna k mnohým vzťah s Hibernate ORM a H2 databázou pomocou anotácií JPA.
Ďalej sme sa dozvedeli o obojsmerných vzťahoch a o tom, ako implementovať pojem vlastniacej strany.
Zdrojový kód v tomto článku nájdete na GitHub.