Vandaag zullen we kijken naar One To Many Mapping in Hibernate. We zullen kijken naar een voorbeeld van Hibernate One To Many Mapping met behulp van annotaties en XML-configuratie.
One To Many Mapping in Hibernate
In eenvoudige bewoordingen betekent one to many mapping dat één rij in een tabel kan worden toegewezen aan meerdere rijen in een andere tabel. Stel je bijvoorbeeld een winkelwagensysteem voor waarin we een andere tabel hebben voor items. Een winkelwagen kan meerdere items bevatten, dus hier hebben we een one to many mapping. We zullen het scenario van winkelwagen-items gebruiken voor ons voorbeeld van hibernate one to many mapping.
One To Many Mapping in Hibernate – Database-instellingen
We kunnen een foreign key constraint gebruiken voor one to many mapping. Hieronder staat ons databasescript voor de tabellen Cart
en Items
. Ik gebruik de MySQL-database voor het voorbeeld van Hibernate one to many mapping. setup.sql
CREATE TABLE `Cart` (
`cart_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`total` decimal(10,0) NOT NULL,
`name` varchar(10) DEFAULT NULL,
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,
`item_id` varchar(10) NOT NULL,
`item_total` decimal(10,0) NOT NULL,
`quantity` int(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `cart_id` (`cart_id`),
CONSTRAINT `items_ibfk_1` FOREIGN KEY (`cart_id`) REFERENCES `Cart` (`cart_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
Hier is het ER-diagram van de Cart- en Items-tabel. Onze database-setup is klaar, laten we doorgaan met het maken van een Hibernate One to Many Mapping voorbeeldproject. Allereerst zullen we XML-gebaseerde configuratie gebruiken en vervolgens implementeren we een mapping van één naar velen met behulp van Hibernate- en JPA-annotaties.
Projectstructuur voor Hibernate One To Many Mapping
Maak een eenvoudig Maven-project in Eclipse of je favoriete IDE, de uiteindelijke projectstructuur ziet eruit zoals op de onderstaande afbeelding.
Hibernate Maven-afhankelijkheden
Ons uiteindelijke pom.xml-bestand bevat afhankelijkheden voor Hibernate en de MySQL-driver. Hibernate maakt gebruik van JBoss-logging en het wordt automatisch toegevoegd als transitieve afhankelijkheden.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.hibernate</groupId>
<artifactId>HibernateOneToManyMapping</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
</dependencies>
</project>
Noteer dat ik de nieuwste versie van Hibernate gebruik, 4.3.5.Final, en de MySQL-driverversie op basis van mijn database-installatie.
Modelklassen voor Hibernate One To Many Mapping
Voor onze tabellen Cart en Items hebben we modelklassen om ze te weerspiegelen. Cart.java
package com.journaldev.hibernate.model;
import java.util.Set;
public class Cart {
private long id;
private double total;
private String name;
private Set<Items> items;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Items> getItems() {
return items;
}
public void setItems(Set<Items> items) {
this.items = items;
}
}
I am using Set of Items, so that every record is unique. We can also use List or Array for one to many mapping in hibernate. Items.java
package com.journaldev.hibernate.model;
public class Items {
private long id;
private String itemId;
private double itemTotal;
private int quantity;
private Cart cart;
// Hibernate vereist een no-args constructor
public Items(){}
public Items(String itemId, double total, int qty, Cart c){
this.itemId=itemId;
this.itemTotal=total;
this.quantity=qty;
this.cart=c;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public double getItemTotal() {
return itemTotal;
}
public void setItemTotal(double itemTotal) {
this.itemTotal = itemTotal;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Cart getCart() {
return cart;
}
public void setCart(Cart cart) {
this.cart = cart;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
Items hebben een many-to-one-relatie met Cart, dus we hebben geen verzameling nodig voor het Cart-object.
Hibernate SessionFactory Utility Class
We hebben een hulpprogramma-klasse voor het maken van een Hibernate SessionFactory. HibernateUtil.java
package com.journaldev.hibernate.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static SessionFactory buildSessionFactory() {
try {
// Maak de SessionFactory aan vanuit hibernate.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
System.out.println("Hibernate Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
System.out.println("Hibernate serviceRegistry created");
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
if(sessionFactory == null) sessionFactory = buildSessionFactory();
return sessionFactory;
}
}
Hibernate Configuration XML-bestand
Ons hibernate-configuratie XML-bestand bevat database-informatie en details over toewijzingsresources. hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">pankaj123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="cart.hbm.xml"/>
<mapping resource="items.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Voorbeeld van Hibernate One To Many Mapping – XML-configuratie
Dit is het belangrijkste deel van de tutorial, laten we zien hoe we zowel de klassen Cart als Items moeten mappen voor een “one to many” mapping in Hibernate. cart.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.journaldev.hibernate.model">
<class name="Cart" table="CART" >
<id name="id" type="long">
<column name="cart_id" />
<generator class="identity" />
</id>
<property name="total" type="double">
<column name="total" />
</property>
<property name="name" type="string">
<column name="name" />
</property>
<set name="items" table="ITEMS" fetch="select">
<key>
<column name="cart_id" not-null="true"></column>
</key>
<one-to-many class="Items"/>
</set>
</class>
</hibernate-mapping>
Het belangrijke deel is het set
-element en het one-to-many
-element erin. Let op dat we een sleutel opgeven die moet worden gebruikt voor de “one to many” mapping, namelijk cart_id. items.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.journaldev.hibernate.model">
<class name="Items" table="ITEMS">
<id name="id" type="long">
<column name="id" />
<generator class="identity" />
</id>
<property name="itemId" type="string">
<column name="item_id"></column>
</property>
<property name="itemTotal" type="double">
<column name="item_total"></column>
</property>
<property name="quantity" type="integer">
<column name="quantity"></column>
</property>
<many-to-one name="cart" class="Cart">
<column name="cart_id" not-null="true"></column>
</many-to-one>
</class>
</hibernate-mapping>
Merk op dat van items naar cart, het een “many to one” relatie is. Dus we moeten het many-to-one
-element gebruiken voor cart en we geven de kolomnaam op die zal worden gemapt met de sleutel. Dus op basis van de Hibernate-mappingconfiguratie van Cart wordt de sleutel cart_id gebruikt voor de mapping. Ons project voor het voorbeeld van Hibernate One To Many Mapping met XML-mapping is klaar, laten we een testprogramma schrijven en controleren of het goed werkt of niet.
Voorbeeld van Hibernate One To Many Mapping – Testprogramma
HibernateOneToManyMain.java
package com.journaldev.hibernate.main;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Cart;
import com.journaldev.hibernate.model.Items;
import com.journaldev.hibernate.util.HibernateUtil;
public class HibernateOneToManyMain {
public static void main(String[] args) {
Cart cart = new Cart();
cart.setName("MyCart");
Items item1 = new Items("I1", 10, 1, cart);
Items item2 = new Items("I2", 20, 2, cart);
Set itemsSet = new HashSet();
itemsSet.add(item1); itemsSet.add(item2);
cart.setItems(itemsSet);
cart.setTotal(10*1 + 20*2);
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try{
//Krijg sessie
sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");
//start transactie
tx = session.beginTransaction();
//Sla de modelobjecten op
session.save(cart);
session.save(item1);
session.save(item2);
//Commiteer transactie
tx.commit();
System.out.println("Cart ID="+cart.getId());
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}finally{
if(!sessionFactory.isClosed()){
System.out.println("Closing SessionFactory");
sessionFactory.close();
}
}
}
}
Merk op dat we zowel de objecten Cart als Items één voor één moeten opslaan. Hibernate zal ervoor zorgen dat de vreemde sleutels in de Items-tabel worden bijgewerkt. Wanneer we het bovenstaande programma uitvoeren, krijgen we de volgende output.
Hibernate Configuration loaded
Hibernate serviceRegistry created
Session created
Hibernate: insert into CART (total, name) values (?, ?)
Hibernate: insert into ITEMS (item_id, item_total, quantity, cart_id) values (?, ?, ?, ?)
Hibernate: insert into ITEMS (item_id, item_total, quantity, cart_id) values (?, ?, ?, ?)
Hibernate: update ITEMS set cart_id=? where id=?
Hibernate: update ITEMS set cart_id=? where id=?
Cart ID=6
Closing SessionFactory
Merk op dat Hibernate een Update-query gebruikt om de cart_id in de ITEMS-tabel in te stellen.
Hibernate één op veel mapping annotatie
Nu we hebben gezien hoe we One To Many-mapping kunnen implementeren in Hibernate met behulp van op XML gebaseerde configuraties, laten we eens kijken hoe we hetzelfde kunnen doen met JPA-annotaties.
Hibernate één op veel mapping voorbeeld annotatie
Het configuratiebestand van Hibernate is bijna hetzelfde, behalve dat het mappingelement verandert omdat we Klassen gebruiken voor hibernate één op veel mapping met annotatie. hibernate-annotation.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">pankaj123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.journaldev.hibernate.model.Cart1"/>
<mapping class="com.journaldev.hibernate.model.Items1"/>
</session-factory>
</hibernate-configuration>
Utilityklasse voor Hibernate SessionFactory
De utilityklasse voor de SessionFactory is bijna hetzelfde, we moeten alleen het nieuwe hibernate-configuratiebestand gebruiken. HibernateAnnotationUtil.java
package com.journaldev.hibernate.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateAnnotationUtil {
private static SessionFactory sessionFactory;
private static SessionFactory buildSessionFactory() {
try {
// Maak de SessionFactory aan vanuit hibernate-annotation.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate-annotation.cfg.xml");
System.out.println("Hibernate Annotation Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
System.out.println("Hibernate Annotation serviceRegistry created");
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
if(sessionFactory == null) sessionFactory = buildSessionFactory();
return sessionFactory;
}
}
Modellen voor Hibernate One To Many Mapping Annotation
Aangezien we geen op XML gebaseerde toewijzingsbestanden hebben, worden alle toewijzingsgerelateerde configuraties gedaan met JPA-annotaties in de modelklassen. Als je op XML gebaseerde toewijzing begrijpt, is het heel eenvoudig en vergelijkbaar. Cart1.java
package com.journaldev.hibernate.model;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="CART")
public class Cart1 {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="cart_id")
private long id;
@Column(name="total")
private double total;
@Column(name="name")
private String name;
@OneToMany(mappedBy="cart1")
private Set items1;
// Getter Setter-methoden voor eigenschappen
}
Belangrijk punt om op te merken is de OneToMany
-annotatie waarbij de variabele mappedBy
wordt gebruikt om de eigenschap in de klasse Items1
te definiëren die voor het toewijzingsdoel zal worden gebruikt. We zouden dus een eigenschap moeten hebben met de naam “cart1” in de klasse Items1. Vergeet niet alle getter-setter-methoden op te nemen. Items1.java
package com.journaldev.hibernate.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="ITEMS")
public class Items1 {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private long id;
@Column(name="item_id")
private String itemId;
@Column(name="item_total")
private double itemTotal;
@Column(name="quantity")
private int quantity;
@ManyToOne
@JoinColumn(name="cart_id", nullable=false)
private Cart1 cart1;
//Hibernate vereist een no-args constructor
public Items1(){}
public Items1(String itemId, double total, int qty, Cart1 c){
this.itemId=itemId;
this.itemTotal=total;
this.quantity=qty;
this.cart1=c;
}
// Getter Setter-methoden
}
Het belangrijkste punt in de bovenstaande klasse is de annotatie ManyToOne
op de variabele Cart1 en de annotatie JoinColumn
om de kolomnaam voor mapping op te geven. Dat is alles voor one-to-many mapping in Hibernate met behulp van annotaties in modelklassen. Vergelijk het met op XML gebaseerde configuraties en je zult ze zeer vergelijkbaar vinden. Laten we een testprogramma schrijven en uitvoeren.
Voorbeeldtestprogramma Hibernate One To Many Mapping met annotaties
Ons testprogramma lijkt gewoon op op XML gebaseerde configuratie, we gebruiken gewoon de nieuwe klassen om de Hibernate Session te verkrijgen en de modelobjecten in de database op te slaan. HibernateOneToManyAnnotationMain.java
package com.journaldev.hibernate.main;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Cart1;
import com.journaldev.hibernate.model.Items1;
import com.journaldev.hibernate.util.HibernateAnnotationUtil;
public class HibernateOneToManyAnnotationMain {
public static void main(String[] args) {
Cart1 cart = new Cart1();
cart.setName("MyCart1");
Items1 item1 = new Items1("I10", 10, 1, cart);
Items1 item2 = new Items1("I20", 20, 2, cart);
Set itemsSet = new HashSet();
itemsSet.add(item1); itemsSet.add(item2);
cart.setItems1(itemsSet);
cart.setTotal(10*1 + 20*2);
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try{
// Verkrijg Session
sessionFactory = HibernateAnnotationUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");
// Start transactie
tx = session.beginTransaction();
// Sla het Modelobject op
session.save(cart);
session.save(item1);
session.save(item2);
// Commit transactie
tx.commit();
System.out.println("Cart1 ID="+cart.getId());
System.out.println("item1 ID="+item1.getId()+", Foreign Key Cart ID="+item1.getCart1().getId());
System.out.println("item2 ID="+item2.getId()+", Foreign Key Cart ID="+item1.getCart1().getId());
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}finally{
if(!sessionFactory.isClosed()){
System.out.println("Closing SessionFactory");
sessionFactory.close();
}
}
}
}
Wanneer we het bovenstaande hibernate one-to-many mapping annotatievoorbeeld uitvoeren, krijgen we de volgende uitvoer.
Hibernate Annotation Configuration loaded
Hibernate Annotation serviceRegistry created
Session created
Hibernate: insert into CART (name, total) values (?, ?)
Hibernate: insert into ITEMS (cart_id, item_id, item_total, quantity) values (?, ?, ?, ?)
Hibernate: insert into ITEMS (cart_id, item_id, item_total, quantity) values (?, ?, ?, ?)
Cart1 ID=7
item1 ID=9, Foreign Key Cart ID=7
item2 ID=10, Foreign Key Cart ID=7
Closing SessionFactory
Dat is alles voor hibernate one-to-many mapping. Download het voorbeeldproject via onderstaande link en doe wat meer experimenten.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-one-to-many-mapping-annotation