Hibernate One to Many Annotation Tutorial

1. Inleiding

Deze korte Hibernate-zelfstudie neemt ons door een voorbeeld van een een te veel mapping met behulp van JPA-annotaties, een alternatief voor XML.

We zullen ook leren wat bidirectionele relaties zijn, hoe ze inconsistenties kunnen veroorzaken en hoe het idee van eigendom kan helpen.

2. Beschrijving

Simpel gezegd,een te veel mapping betekent dat een rij in een tabel wordt toegewezen aan meerdere rijen in een andere tabel.

Laten we eens kijken naar het volgende entiteitsrelatiediagram om een ​​te zien een te veel vereniging:

Voor dit voorbeeld implementeren we een wagensysteem waarbij we een tafel hebben voor elke wagen en een andere tafel voor elk item. Een winkelwagen kan veel items bevatten, dus hier hebben we een een te veel in kaart brengen.

De manier waarop dit werkt op databaseniveau is dat we een cart_id als primaire sleutel in het winkelwagen tafel en ook een cart_id als een externe sleutel in items.

De manier waarop we het in code doen, is met @Een te veel.

Laten we het Winkelwagen klasse naar de Artikelen object op een manier die de relatie in de database weerspiegelt:

openbare klasse Cart {// ... @OneToMany (mappedBy = "cart") privésetitems; // ...}

We kunnen ook een verwijzing naar toevoegen Winkelwagen in Artikelen gebruik makend van @ManyToOne, waardoor dit een bidirectionele relatie is. Bidirectioneel betekent dat we hebben toegang items van karren, en ook karren van items.

De mappedBy eigenschap is wat we gebruiken om Hibernate te vertellen welke variabele we gebruiken om de bovenliggende klasse in onze onderliggende klasse te vertegenwoordigen.

De volgende technologieën en bibliotheken worden gebruikt om een ​​voorbeeld van een Hibernate-toepassing te ontwikkelen die implementeert een te veel vereniging:

  • JDK 1.8 of hoger
  • Slaapstand 5
  • Maven 3 of hoger
  • H2-database

3. Installatie

3.1. Database-instellingen

Hieronder vindt u ons databasescript voor Winkelwagen en Artikelen tafels. We gebruiken de beperking van de externe sleutel voor een te veel in kaart brengen:

CREATE TABLE `Cart` (` cart_id` int (11) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`cart_id`)) ENGINE = InnoDB AUTO_INCREMENT = 5 STANDAARD CHARSET = utf8; TABEL MAKEN `Items` (` id` int (11) unsigned NOT NULL AUTO_INCREMENT, `cart_id` int (11) unsigned NOT NULL, PRIMARY KEY (` id`), KEY `cart_id` (` cart_id`), BEPERKING `items_ibfk_1 `FOREIGN KEY (` cart_id`) REFERENTIES `Cart` (` cart_id`)) ENGINE = InnoDB AUTO_INCREMENT = 7 STANDAARD CHARSET = utf8;

Onze database-instellingen zijn klaar, dus laten we verder gaan met het maken van het Hibernate-voorbeeldproject.

3.2. Afhankelijkheden van Maven

We zullen dan de Hibernate- en H2-stuurprogramma-afhankelijkheden toevoegen aan onze pom.xml het dossier. De Hibernate-afhankelijkheid maakt gebruik van JBoss-logboekregistratie en wordt automatisch toegevoegd als transitieve afhankelijkheden:

  • Slaapstand versie 5.2.7.Finale
  • H2 driver versie 1.4.197

Bezoek de centrale opslagplaats van Maven voor de nieuwste versies van Hibernate en de H2-afhankelijkheden.

3.3. Slaapstandconfiguratie

Hier is de configuratie van Hibernate:

  org.h2.Driver jdbc: h2: mem: spring_hibernate_one_to_many sa org.hibernate.dialect.H2Dialect thread true 

3.4. HibernateAnnotationUtil Klasse

Met de HibernateAnnotationUtil class, hoeven we alleen maar te verwijzen naar het nieuwe Hibernate-configuratiebestand:

privé statische SessionFactory sessionFactory; private SessionFactory buildSessionFactory () {ServiceRegistry serviceRegistry = nieuwe StandardServiceRegistryBuilder (). configureren ("slaapstand-annotatie.cfg.xml"). build (); Metadata metadata = nieuwe MetadataSources (serviceRegistry) .getMetadataBuilder (). Build (); SessionFactory sessionFactory = metadata.getSessionFactoryBuilder (). Build (); return sessionFactory; } openbare SessionFactory getSessionFactory () {if (sessionFactory == null) sessionFactory = buildSessionFactory (); return sessionFactory; }

4. De modellen

De mapping-gerelateerde configuraties worden gedaan met behulp van JPA-annotaties in de modelklassen:

@Entity @Table (name = "CART") openbare klasse Cart {// ... @OneToMany (mappedBy = "cart") privésetitems; // getters en setters}

Houd er rekening mee dat de @Een te veel annotatie wordt gebruikt om de eigenschap te definiëren in Artikelen klasse die zal worden gebruikt om de mappedBy variabele. Daarom hebben we een woning met de naam "winkelwagen" in de Artikelen klasse:

@Entity @Table (name = "ITEMS") openbare klasse-items {// ... @ManyToOne @JoinColumn (name = "cart_id", nullable = false) privé winkelwagentje; openbare items () {} // getters en setters} 

Het is ook belangrijk op te merken dat de @ManyToOne annotatie is gekoppeld aan de Winkelwagen class variabele. @JoinColumn annotatie verwijst naar de toegewezen kolom.

5. In actie

In het testprogramma maken we een klas met een hoofd() methode voor het ophalen van de slaapsessie en het opslaan van de modelobjecten in de database die het een te veel vereniging:

sessionFactory = HibernateAnnotationUtil.getSessionFactory (); session = sessionFactory.getCurrentSession (); System.out.println ("Sessie aangemaakt"); tx = session.beginTransaction (); session.save (winkelwagen); session.save (item1); session.save (item2); tx.commit (); System.out.println ("Cartitem1, Foreign Key Cartitem2, Foreign Key Cartmany-to-one">6. Het @ManyToOne Annotatie

Zoals we in sectie 2 hebben gezien, kunnen we een veel-op-een relatie met behulp van de @ManyToOne annotatie. EEN veel-op-een mapping betekent dat veel instanties van deze entiteit worden toegewezen aan een instantie van een andere entiteit - veel items in één winkelwagen.

De @ManyToOne Met annotatie kunnen we ook bidirectionele relaties creëren. We zullen dit in de volgende subsecties in detail behandelen.

6.1. Inconsistenties en eigendom

Nu als Winkelwagen verwezen Artikelen, maar Artikelen verwees niet op zijn beurt Winkelwagen, onze relatie zou eenrichtingsverkeer zijn. De objecten zouden ook een natuurlijke consistentie hebben.

In ons geval is de relatie echter bidirectioneel, het mogelijk maken van inconsistentie.

Laten we ons een situatie voorstellen waarin een ontwikkelaar iets wil toevoegen item 1 naar winkelwagen en item2 naar winkelwagen2, maar maakt een fout waardoor de verwijzingen tussen winkelwagen2 en item2 inconsistent worden:

Winkelwagen cart1 = nieuwe winkelwagen (); Winkelwagen cart2 = nieuwe winkelwagen (); Items item1 = nieuwe items (cart1); Items item2 = nieuwe items (cart2); Set itemsSet = new HashSet (); itemsSet.add (item1); itemsSet.add (item2); cart1.setItems (itemsSet); // mis!

Zoals hierboven getoond, item2 referenties cart2, terwijl winkelwagen2 verwijst niet item2, en dat is slecht.

Hoe moet de slaapstand opslaan item2 naar de database? Zullen item2 verwijzing naar externe sleutel winkelwagen1 of winkelwagen2?

We lossen deze dubbelzinnigheid op met behulp van het idee van een eigen kant van de relatie; referenties die tot de eigenaar behoren, hebben voorrang en worden opgeslagen in de database.

6.2. Artikelen als de eigenaars

Zoals vermeld in de JPA-specificatie onder paragraaf 2.9, het is een goede gewoonte om te markeren veel-op-een kant als de bezitterige kant.

Met andere woorden, iktems zou de bezitter zijn en Winkelwagen de omgekeerde kant, en dat is precies wat we eerder deden.

Dus hoe hebben we dit bereikt?

Door de mappedBy attribuut in het Winkelwagen klasse, we markeren het als de omgekeerde zijde.

Tegelijkertijd annoteren we ook de Artikelen.winkelwagen veld met @ManyToOne, maken Artikelen de bezitterige kant.

Terugkomend op ons voorbeeld van "inconsistentie", nu weet Hibernate dat de item2‘S referentie is belangrijker en zal redden item2‘S verwijzing naar de database.

Laten we het resultaat eens bekijken:

item1 ID = 1, Foreign Key Cart ID = 1 item2 ID = 2, Foreign Key Cart ID = 2

Hoewel winkelwagen referenties item2 in ons fragment, item2‘S verwijzing naar winkelwagen2 wordt opgeslagen in de database.

6.3. Winkelwagen als de eigenaar

Het is ook mogelijk om het een te veel kant als de bezitterige kant, en veel-op-een zijde als de omgekeerde zijde.

Hoewel dit niet een aanbevolen praktijk is, laten we het toch proberen.

Het onderstaande codefragment toont de implementatie van een te veel kant als eigendomskant:

openbare klasse ItemsOIO {// ... @ManyToOne @JoinColumn (name = "cart_id", insertable = false, updatable = false) privé CartOIO-winkelwagentje; // ..} openbare klasse CartOIO {// .. @OneToMany @JoinColumn (name = "cart_id") // we moeten de fysieke informatie privé-setitems dupliceren; // ..} 

Merk op hoe we het mappedBy element en stel het veel-op-een @JoinColumn net zo insteekbaar en bij te werken naar false.

Als we dezelfde code uitvoeren, is het resultaat het tegenovergestelde:

item1 ID = 1, Foreign Key Cart ID = 1 item2 ID = 2, Foreign Key Cart ID = 1

Zoals hierboven getoond, nu item2 hoort bij winkelwagen.

7. Conclusie

We hebben gezien hoe gemakkelijk het is om het een te veel relatie met de Hibernate ORM- en H2-database met behulp van JPA-annotaties.

Daarnaast leerden we over bidirectionele relaties en hoe we het idee van een eigen kant kunnen implementeren.

De broncode in dit artikel is te vinden op GitHub.


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