Vandaag zullen we kijken naar One to One Mapping in Hibernate. We zullen een voorbeeld bekijken van Hibernate One To One Mapping met zowel annotatie als XML-configuratie.
One to One Mapping in Hibernate
Meestal zijn database-tabellen met elkaar verbonden. Er zijn veel vormen van associatie – one-to-one, one-to-many en many-to-many zijn op het brede niveau. Deze kunnen verder worden onderverdeeld in unidirectionele en bidirectionele mappings. Vandaag zullen we kijken naar de implementatie van Hibernate One to One Mapping met behulp van XML-configuratie en ook met annotatieconfiguratie.
Hibernate One to One Mapping Voorbeeld Database Setup
Eerst zouden we een één-op-één mapping moeten instellen in database tabellen. We zullen twee tabellen maken voor ons voorbeeld – Transactie en Klant. Beide tabellen zullen een één-op-één mapping hebben. Transactie zal de primaire tabel zijn en we zullen Foreign Key gebruiken in de Klantentabel voor één-op-één mapping. Ik geef hier de MySQL-script, dat is de database die ik gebruik voor deze tutorial. Als je een andere database gebruikt, zorg er dan voor dat je het script dienovereenkomstig aanpast.
-- Maak Transactietabel
CREATE TABLE `Transaction` (
`txn_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`txn_date` date NOT NULL,
`txn_total` decimal(10,0) NOT NULL,
PRIMARY KEY (`txn_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
-- Maak Klantentabel
CREATE TABLE `Customer` (
`txn_id` int(11) unsigned NOT NULL,
`cust_name` varchar(20) NOT NULL DEFAULT '',
`cust_email` varchar(20) DEFAULT NULL,
`cust_address` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`txn_id`),
CONSTRAINT `customer_ibfk_1` FOREIGN KEY (`txn_id`) REFERENCES `Transaction` (`txn_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Entiteitsrelatiediagram (ERD) van de bovenstaande één-op-één mapping tussen tabellen ziet eruit als de onderstaande afbeelding. Onze databaseconfiguratie is klaar, laten we nu doorgaan met het Hibernate One to One Example Project.
Hibernate One to One Mapping Voorbeeld Projectstructuur
Creëer een eenvoudig Maven-project in je Java IDE, ik gebruik Eclipse. Onze uiteindelijke projectstructuur zal eruit zien als de onderstaande afbeelding. Allereerst zullen we kijken naar een voorbeeld van XML-gebaseerde Hibernate One-to-One Mapping en vervolgens zullen we hetzelfde implementeren met annotaties.
Hibernate Maven-afhankelijkheden
Ons uiteindelijke pom.xml-bestand ziet er als volgt uit.
<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>HibernateOneToOneMapping</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>
De afhankelijkheden zijn alleen voor Hibernate en de MySQL Java-driver. Let op dat ik de nieuwste versie van Hibernate gebruik 4.3.5.Final en de MySQL Java-driver op basis van mijn MySQL-databaseversie (5.0.5). Hibernate 4 gebruikt JBoss logging en wordt automatisch geïmporteerd als transitatieve afhankelijkheid. Je kunt dit bevestigen in de Maven-afhankelijkheden van het project. Als je oudere versies van Hibernate gebruikt, moet je mogelijk slf4j-afhankelijkheden toevoegen.
Hibernate One-to-One Mapping Modelklassen
Modelklassen voor Hibernate One-to-One mapping om database tabellen weer te geven zouden er als volgt uitzien.
package com.journaldev.hibernate.model;
import java.util.Date;
public class Txn {
private long id;
private Date date;
private double total;
private Customer customer;
@Override
public String toString(){
return id+", "+total+", "+customer.getName()+", "+customer.getEmail()+", "+customer.getAddress();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
package com.journaldev.hibernate.model;
public class Customer {
private long id;
private String name;
private String email;
private String address;
private Txn txn;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Txn getTxn() {
return txn;
}
public void setTxn(Txn txn) {
this.txn = txn;
}
}
Sinds we XML-gebaseerde configuratie gebruiken voor mapping, zijn de bovenstaande modelklassen eenvoudige POJO-klassen of Java Beans met getter-setter-methoden. Ik gebruik de klasse-naam Txn
om verwarring te voorkomen, omdat de Hibernate API een klasse-naam heeft als Transaction
.
Hibernate One to One Mapping Configuration
Laten we Hibernate one-to-one mapping configuratiebestanden maken voor de tabellen Txn en Customer. txn.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>
<class name="com.journaldev.hibernate.model.Txn" table="TRANSACTION" >
<id name="id" type="long">
<column name="txn_id" />
<generator class="identity" />
</id>
<property name="date" type="date">
<column name="txn_date" />
</property>
<property name="total" type="double">
<column name="txn_total" />
</property>
<one-to-one name="customer" class="com.journaldev.hibernate.model.Customer"
cascade="save-update" />
</class>
</hibernate-mapping>
Het belangrijke punt om hierboven op te merken, is het hibernate one-to-one
-element voor de customer-eigenschap. customer.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>
<class name="com.journaldev.hibernate.model.Customer" table="CUSTOMER">
<id name="id" type="long">
<column name="txn_id" />
<generator class="foreign">
<param name="property">txn</param>
</generator>
</id>
<one-to-one name="txn" class="com.journaldev.hibernate.model.Txn"
constrained="true"></one-to-one>
<property name="name" type="string">
<column name="cust_name"></column>
</property>
<property name="email" type="string">
<column name="cust_email"></column>
</property>
<property name="address" type="string">
<column name="cust_address"></column>
</property>
</class>
</hibernate-mapping>
generator class=“foreign” is het belangrijke deel dat wordt gebruikt voor de hibernate-implementatie van de foreign key.
Hibernate Configuration File
Hier is het hibernate-configuratiebestand voor XML-gebaseerde hibernate-mappingconfiguratie. 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="txn.hbm.xml"/>
<mapping resource="customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Het hibernate-configuratiebestand is eenvoudig en bevat databaseverbindingseigenschappen en hibernate-mappingresources.
Hibernate SessionFactory Utility
Hier is de hulpprogramma klasse om een Hibernate SessionFactory-instantie te creëren.
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;
}
}
Dat is het, laten we een testprogramma schrijven om de hibernate one-to-one mapping xml-gebaseerde configuratie te testen.
Hibernate One-to-One Mapping XML Configuratie Testprogramma
In het hibernate one-to-one mapping voorbeeld testprogramma zullen we eerst een Txn-object maken en het opslaan. Nadat het in de database is opgeslagen, zullen we de gegenereerde id gebruiken om het Txn-object op te halen en af te drukken.
package com.journaldev.hibernate.main;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Customer;
import com.journaldev.hibernate.model.Txn;
import com.journaldev.hibernate.util.HibernateUtil;
public class HibernateOneToOneMain {
public static void main(String[] args) {
Txn txn = buildDemoTransaction();
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try{
// Krijg Session
sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");
// start transactie
tx = session.beginTransaction();
// Bewaar het Model-object
session.save(txn);
// Commit transactie
tx.commit();
System.out.println("Transaction ID="+txn.getId());
// Krijg opgeslagen transactiegegevens
printTransactionData(txn.getId(), sessionFactory);
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}finally{
if(!sessionFactory.isClosed()){
System.out.println("Closing SessionFactory");
sessionFactory.close();
}
}
}
private static void printTransactionData(long id, SessionFactory sessionFactory) {
Session session = null;
Transaction tx = null;
try{
// Krijg Session
sessionFactory = HibernateUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
// start transactie
tx = session.beginTransaction();
// Bewaar het Model-object
Txn txn = (Txn) session.get(Txn.class, id);
// Commit transactie
tx.commit();
System.out.println("Transaction Details=\n"+txn);
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}
}
private static Txn buildDemoTransaction() {
Txn txn = new Txn();
txn.setDate(new Date());
txn.setTotal(100);
Customer cust = new Customer();
cust.setAddress("Bangalore, India");
cust.setEmail("[email protected]");
cust.setName("Pankaj Kumar");
txn.setCustomer(cust);
cust.setTxn(txn);
return txn;
}
}
Nu, wanneer we het bovenstaande one-to-one mapping in hibernate-testprogramma uitvoeren, krijgen we de volgende uitvoer.
Hibernate Configuration loaded
Hibernate serviceRegistry created
Session created
Hibernate: insert into TRANSACTION (txn_date, txn_total) values (?, ?)
Hibernate: insert into CUSTOMER (cust_name, cust_email, cust_address, txn_id) values (?, ?, ?, ?)
Transaction ID=19
Hibernate: select txn0_.txn_id as txn_id1_1_0_, txn0_.txn_date as txn_date2_1_0_, txn0_.txn_total as txn_tota3_1_0_,
customer1_.txn_id as txn_id1_0_1_, customer1_.cust_name as cust_nam2_0_1_, customer1_.cust_email as cust_ema3_0_1_,
customer1_.cust_address as cust_add4_0_1_ from TRANSACTION txn0_ left outer join CUSTOMER customer1_ on
txn0_.txn_id=customer1_.txn_id where txn0_.txn_id=?
Transaction Details=
19, 100.0, Pankaj Kumar, [email protected], Bangalore, India
Closing SessionFactory
Zoals u kunt zien, werkt het prima en kunnen we gegevens ophalen uit beide tabellen met behulp van transactie-id. Controleer de SQL die Hibernate intern gebruikt om de gegevens op te halen, het gebruikt joins om de gegevens uit beide tabellen te verkrijgen.
Hibernate One-to-One Mapping Annotation
In het bovenstaande gedeelte zagen we hoe we XML-gebaseerde configuratie kunnen gebruiken voor Hibernate one-to-one mapping. Laten we nu kijken hoe we JPA en Hibernate-annotaties kunnen gebruiken om hetzelfde te bereiken.
Hibernate Configuratiebestand
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.Txn1"/>
<mapping class="com.journaldev.hibernate.model.Customer1"/>
</session-factory>
</hibernate-configuration>
Hibernate-configuratie is eenvoudig, zoals u kunt zien heb ik twee modelklassen die we zullen gebruiken met annotaties – Txn1
en Customer1
.
Hibernate One-to-One Mapping Annotation Voorbeeld Model Klassen
Voor hibernate one-to-one mapping annotatieconfiguratie zijn modelklassen het belangrijkste onderdeel. Laten we eens kijken hoe onze modelklassen eruitzien.
package com.journaldev.hibernate.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
@Entity
@Table(name="TRANSACTION")
public class Txn1 {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="txn_id")
private long id;
@Column(name="txn_date")
private Date date;
@Column(name="txn_total")
private double total;
@OneToOne(mappedBy="txn")
@Cascade(value=org.hibernate.annotations.CascadeType.SAVE_UPDATE)
private Customer1 customer;
@Override
public String toString(){
return id+", "+total+", "+customer.getName()+", "+customer.getEmail()+", "+customer.getAddress();
}
//Getter-Setter-methoden weggelaten voor duidelijkheid
}
Merk op dat de meeste annotaties afkomstig zijn van de Java Persistence API omdat Hibernate de implementatie ervan levert. Voor cascadering moeten we echter de Hibernate-annotatie org.hibernate.annotations.Cascade
en enum org.hibernate.annotations.CascadeType
gebruiken.
package com.journaldev.hibernate.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Entity
@Table(name="CUSTOMER")
public class Customer1 {
@Id
@Column(name="txn_id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters={@Parameter(name="property", value="txn")})
private long id;
@Column(name="cust_name")
private String name;
@Column(name="cust_email")
private String email;
@Column(name="cust_address")
private String address;
@OneToOne
@PrimaryKeyJoinColumn
private Txn1 txn;
//Getter-Setter-methoden
}
Merk op dat we @GenericGenerator
zouden moeten gebruiken, zodat het id uit de transactie wordt gebruikt in plaats van het te genereren.
Hibernate SessionFactory Utility-klasse
Het maken van een SessionFactory is onafhankelijk van de manier waarop we hibernate-mapping verstrekken. Onze hulpprogramma-klasse voor het maken van een SessionFactory ziet er als volgt uit.
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 van 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-One Mapping Annotatie Voorbeeld Testprogramma
Hier is een eenvoudig testprogramma voor ons hibernate one-to-one mapping annotatievoorbeeld.
package com.journaldev.hibernate.main;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Customer1;
import com.journaldev.hibernate.model.Txn1;
import com.journaldev.hibernate.util.HibernateAnnotationUtil;
public class HibernateOneToOneAnnotationMain {
public static void main(String[] args) {
Txn1 txn = buildDemoTransaction();
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try{
//Ontvang Sessie
sessionFactory = HibernateAnnotationUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created using annotations configuration");
//start transactie
tx = session.beginTransaction();
//Modelobject Opslaan
session.save(txn);
//Transactie committeren
tx.commit();
System.out.println("Annotation Example. Transaction ID="+txn.getId());
//Ontvang opgeslagen Transactiegegevens
printTransactionData(txn.getId(), sessionFactory);
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}finally{
if(sessionFactory != null && !sessionFactory.isClosed()){
System.out.println("Closing SessionFactory");
sessionFactory.close();
}
}
}
private static void printTransactionData(long id, SessionFactory sessionFactory) {
Session session = null;
Transaction tx = null;
try{
//Ontvang Sessie
sessionFactory = HibernateAnnotationUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
//start transactie
tx = session.beginTransaction();
//Modelobject Opslaan
Txn1 txn = (Txn1) session.get(Txn1.class, id);
//Transactie committeren
tx.commit();
System.out.println("Annotation Example. Transaction Details=\n"+txn);
}catch(Exception e){
System.out.println("Exception occured. "+e.getMessage());
e.printStackTrace();
}
}
private static Txn1 buildDemoTransaction() {
Txn1 txn = new Txn1();
txn.setDate(new Date());
txn.setTotal(100);
Customer1 cust = new Customer1();
cust.setAddress("San Jose, USA");
cust.setEmail("[email protected]");
cust.setName("Pankaj Kr");
txn.setCustomer(cust);
cust.setTxn(txn);
return txn;
}
}
Hier is het outputfragment wanneer we het bovenstaande programma uitvoeren.
Hibernate Annotation Configuration loaded
Hibernate Annotation serviceRegistry created
Session created using annotations configuration
Hibernate: insert into TRANSACTION (txn_date, txn_total) values (?, ?)
Hibernate: insert into CUSTOMER (cust_address, cust_email, cust_name, txn_id) values (?, ?, ?, ?)
Annotation Example. Transaction ID=20
Hibernate: select txn1x0_.txn_id as txn_id1_1_0_, txn1x0_.txn_date as txn_date2_1_0_, txn1x0_.txn_total as txn_tota3_1_0_,
customer1x1_.txn_id as txn_id1_0_1_, customer1x1_.cust_address as cust_add2_0_1_, customer1x1_.cust_email as cust_ema3_0_1_,
customer1x1_.cust_name as cust_nam4_0_1_ from TRANSACTION txn1x0_ left outer join CUSTOMER customer1x1_ on
txn1x0_.txn_id=customer1x1_.txn_id where txn1x0_.txn_id=?
Annotation Example. Transaction Details=
20, 100.0, Pankaj Kr, [email protected], San Jose, USA
Closing SessionFactory
Merk op dat de output vergelijkbaar is met de Hibernate one-to-one XML-gebaseerde configuratie. Dat is alles voor het Hibernate one-to-one mapping-voorbeeld. Je kunt het eindproject downloaden via onderstaande link en ermee experimenteren om meer te leren.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-one-to-one-mapping-example-annotation