Hibernate One To Many Mapping Beispiel Annotation

Heute werden wir uns die One-to-Many-Mapping in Hibernate ansehen. Wir werden ein Beispiel für Hibernate One-to-Many-Mapping verwenden, sowohl mit Annotation als auch mit XML-Konfiguration.

One-to-Many-Mapping in Hibernate

In einfachen Worten bedeutet One-to-Many-Mapping, dass eine Zeile in einer Tabelle mehreren Zeilen in einer anderen Tabelle zugeordnet werden kann. Zum Beispiel, denken Sie an ein Warenkorb-System, in dem wir eine weitere Tabelle für Artikel haben. Ein Warenkorb kann mehrere Artikel haben, daher haben wir hier ein One-to-Many-Mapping. Wir werden das Szenario Warenkorb-Artikel für unser Hibernate One-to-Many-Mapping-Beispiel verwenden.

One-to-Many-Mapping in Hibernate – Datenbank-Setup

Wir können einen Fremdschlüssel-Constraint für das One-to-Many-Mapping verwenden. Unten ist unser Datenbank-Skript für die Tabellen Cart und Items. Ich verwende die MySQL-Datenbank für das Beispiel des Hibernate One-to-Many-Mappings. 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;

Unten befindet sich das ER-Diagramm der Tabellen Cart und Items. Unsere Datenbankkonfiguration ist bereit, wir gehen nun zur Erstellung eines Hibernate One-to-Many-Mapping-Beispielprojekts über. Zunächst verwenden wir eine XML-basierte Konfiguration und dann implementieren wir das One-to-Many-Mapping mithilfe von Hibernate und JPA-Annotationen.

Hibernate One-to-Many-Mapping Projektstruktur

Erstellen Sie ein einfaches Maven-Projekt in Eclipse oder Ihrer bevorzugten IDE, die endgültige Projektstruktur wird wie auf dem untenstehenden Bild aussehen.

Hibernate Maven-Abhängigkeiten

Unsere endgültige pom.xml-Datei enthält Abhängigkeiten für Hibernate und den MySQL-Treiber. Hibernate verwendet das JBoss-Logging, das automatisch als transitive Abhängigkeiten hinzugefügt wird.

<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>

Beachten Sie, dass ich die neueste Hibernate-Version 4.3.5.Final und die MySQL-Treiber-Version gemäß meiner Datenbankinstallation verwende.

Hibernate One To Many Mapping Model Klassen

Für unsere Tabellen Cart und Items haben wir Modellklassen, um sie widerzuspiegeln. 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 erfordert einen Konstruktor ohne Argumente
	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 haben eine Many-to-One-Beziehung zu Cart, daher benötigen wir keine Sammlung für das Cart-Objekt.

Hibernate SessionFactory Utility-Klasse

Wir haben eine Hilfsklasse zur Erstellung der 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 {
            // Erstellen Sie die SessionFactory aus 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-Konfigurations-XML-Datei

Unsere Hibernate-Konfigurations-XML-Datei enthält Datenbankinformationen und Details zur Zuordnung von Ressourcen. 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>

Beispiel für Hibernate One To Many Mapping – XML-Konfiguration

Dies ist der wichtigste Teil des Tutorials. Schauen wir uns an, wie wir die Klassen Cart und Items für eine One-to-Many-Mapping in Hibernate abbilden müssen. 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>

Der wichtige Teil ist das set-Element und das one-to-many-Element darin. Beachten Sie, dass wir einen Schlüssel angeben, der für das One-to-Many-Mapping verwendet wird, d. h. 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>

Beachten Sie, dass es sich von Items zu Cart um eine Many-to-One-Beziehung handelt. Daher müssen wir das many-to-one-Element für Cart verwenden, und wir geben den Spaltennamen an, der mit dem Schlüssel abgebildet wird. Basierend auf der Hibernate-Mappingkonfiguration für Cart wird sein Schlüssel cart_id für das Mapping verwendet. Unser Projekt für das Hibernate One To Many Mapping-Beispiel unter Verwendung der XML-Mapping ist bereit. Lassen Sie uns ein Testprogramm schreiben und überprüfen, ob es funktioniert oder nicht.

Beispiel für Hibernate One To Many Mapping – Testprogramm

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{
		//Holen Sie die Sitzung
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.getCurrentSession();
		System.out.println("Session created");
		//Transaktion starten
		tx = session.beginTransaction();
		
		//Speichern der Modellobjekte
		session.save(cart);
		session.save(item1);
		session.save(item2);
		
		//Transaktion bestätigen
		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();
			}
		}
	}

}

Beachten Sie, dass wir sowohl die Warenkorb- als auch die Artikelobjekte einzeln speichern müssen. Hibernate kümmert sich um die Aktualisierung der Fremdschlüssel in der Tabelle „Artikel“. Wenn wir das obige Programm ausführen, erhalten wir folgende Ausgabe.

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

Beachten Sie, dass Hibernate eine Update-Abfrage verwendet, um die cart_id in der ITEMS-Tabelle festzulegen.

Hibernate One To Many Mapping Annotation

Jetzt, da wir gesehen haben, wie man eine One-To-Many-Zuordnung in Hibernate unter Verwendung von XML-basierten Konfigurationen implementiert, sehen wir, wie wir dasselbe unter Verwendung von JPA-Annotationen tun können.

Hibernate One To Many Mapping Beispiel Annotation

Die Hibernate-Konfigurationsdatei ist fast gleich, außer dass sich das Mapping-Element ändert, weil wir Klassen für die Hibernate-One-to-Many-Zuordnung mit Annotation verwenden. 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>

Hibernate SessionFactory Utility Class

Die Utility-Klasse SessionFactory ist fast gleich, wir müssen nur die neue Hibernate-Konfigurationsdatei verwenden. 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 {
            // Erstellt die SessionFactory aus 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;
    }
}

Hibernate One To Many Mapping Annotation Model Klassen

Da wir keine XML-basierten Zuordnungsdateien haben, werden alle Zuordnungsbezogenen Konfigurationen mit JPA-Annotationen in den Modellklassen durchgeführt. Wenn Sie das XML-basierte Mapping verstehen, ist es sehr einfach und ähnlich. 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 für Eigenschaften
}

Wichtig ist die OneToMany-Annotation, bei der die Variable mappedBy verwendet wird, um die Eigenschaft in der Klasse Items1 zu definieren, die für den Zuordnungszweck verwendet wird. Daher sollten wir eine Eigenschaft mit dem Namen „cart1“ in der Klasse Items1 haben. Vergessen Sie nicht, alle Getter-Setter-Methoden einzuschließen. 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 benötigt einen no-args-Konstruktor
	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
}

Der wichtigste Punkt in der obigen Klasse ist die ManyToOne-Annotation auf der Cart1-Klassenvariable und die JoinColumn-Annotation, um den Spaltennamen für die Zuordnung anzugeben. Das ist alles für die One-to-Many-Zuordnung in Hibernate unter Verwendung von Annotationen in den Modellklassen. Vergleichen Sie es mit XML-basierten Konfigurationen, Sie werden feststellen, dass sie sehr ähnlich sind. Lassen Sie uns ein Testprogramm schreiben und es ausführen.

Beispieltestprogramm für Hibernate One-To-Many-Mapping mit Annotationen

Unser Testprogramm ist ähnlich wie eine XML-basierte Konfiguration. Wir verwenden einfach die neuen Klassen, um die Hibernate-Sitzung zu erhalten und die Modellobjekte in die Datenbank zu speichern. 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{
		//Sitzung erhalten
		sessionFactory = HibernateAnnotationUtil.getSessionFactory();
		session = sessionFactory.getCurrentSession();
		System.out.println("Session created");
		//Transaktion starten
		tx = session.beginTransaction();
		//Modellobjekt speichern
		session.save(cart);
		session.save(item1);
		session.save(item2);
		//Transaktion bestätigen
		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();
			}
		}
	}

}

Wenn wir das obige Hibernate-One-to-Many-Mapping-Beispieltestprogramm ausführen, erhalten wir folgende Ausgabe.

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

Das ist alles für das Hibernate-One-to-Many-Mapping. Laden Sie das Beispielprojekt von unten herunter und führen Sie weitere Experimente durch.

Hibernate OneToMany Mapping Projekt herunterladen

Source:
https://www.digitalocean.com/community/tutorials/hibernate-one-to-many-mapping-annotation