One to One XML Mapping in Hibernate
Let us understand about One to One XML Mapping in Hibernate
In this relation mapping, one object of a class is associated with only one object of another class.
In other words,
One record of a table is associated with only one record of another table.
In this mapping, both the tables will share the common primary key.
Example:
Consider the relation between Applicant and Passport
One Applicant will have only one Passport.
Let’s develop One To One relation between Applicant and Passport
Relation looks as below
As shown in the above ER diagram, Relation between Applicant and Passport is One To One.
Passport_Id column is the primary key of Passport table
Applicant_Id column is the primary key of Applicant table
Note:
Both Applicant and Passport tables will share the same value for primary key. Hence Applicant_Id and Passport_Id will have the same value for each record.
Step 1
Create hibernate project
Please refer Hibernate setup in eclipse article on how to do it.
Project structure
Step 2
Update pom.xml with Hibernate and Mysql dependencies
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>OneToOneXML</groupId>
- <artifactId>OneToOneXML</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>OneToOneXML</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-core</artifactId>
- <version>5.2.6.Final</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>6.0.5</version>
- </dependency>
- </dependencies>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>OneToOneXML</groupId> <artifactId>OneToOneXML</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>OneToOneXML</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.6.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.5</version> </dependency> </dependencies> </project>
Step 3
Create Applicant class
- package com.kb.model;
- public class Applicant {
- private int applicantId;
- private String name;
- private int age;
- private String city;
- private Passport passport;
- public int getApplicantId() {
- return applicantId;
- }
- public void setApplicantId(int applicantId) {
- this.applicantId = applicantId;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getCity() {
- return city;
- }
- public void setCity(String city) {
- this.city = city;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public Passport getPassport() {
- return passport;
- }
- public void setPassport(Passport passport) {
- this.passport = passport;
- }
- }
package com.kb.model; public class Applicant { private int applicantId; private String name; private int age; private String city; private Passport passport; public int getApplicantId() { return applicantId; } public void setApplicantId(int applicantId) { this.applicantId = applicantId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Passport getPassport() { return passport; } public void setPassport(Passport passport) { this.passport = passport; } }
Applicant class has a reference of Passport class to maintain One to One relation.
Step 4
Create Passport class
- package com.kb.model;
- import java.util.Date;
- public class Passport {
- private int passportId;
- private String passportNumber;
- private Date issuedDate;
- private Date expiryDate;
- private Applicant applicant;
- public int getPassportId() {
- return passportId;
- }
- public void setPassportId(int passportId) {
- this.passportId = passportId;
- }
- public String getPassportNumber() {
- return passportNumber;
- }
- public void setPassportNumber(String passportNumber) {
- this.passportNumber = passportNumber;
- }
- public Date getIssuedDate() {
- return issuedDate;
- }
- public void setIssuedDate(Date issuedDate) {
- this.issuedDate = issuedDate;
- }
- public Date getExpiryDate() {
- return expiryDate;
- }
- public void setExpiryDate(Date expiryDate) {
- this.expiryDate = expiryDate;
- }
- public Applicant getApplicant() {
- return applicant;
- }
- public void setApplicant(Applicant applicant) {
- this.applicant = applicant;
- }
- }
package com.kb.model; import java.util.Date; public class Passport { private int passportId; private String passportNumber; private Date issuedDate; private Date expiryDate; private Applicant applicant; public int getPassportId() { return passportId; } public void setPassportId(int passportId) { this.passportId = passportId; } public String getPassportNumber() { return passportNumber; } public void setPassportNumber(String passportNumber) { this.passportNumber = passportNumber; } public Date getIssuedDate() { return issuedDate; } public void setIssuedDate(Date issuedDate) { this.issuedDate = issuedDate; } public Date getExpiryDate() { return expiryDate; } public void setExpiryDate(Date expiryDate) { this.expiryDate = expiryDate; } public Applicant getApplicant() { return applicant; } public void setApplicant(Applicant applicant) { this.applicant = applicant; } }
Passport class has a reference of Applicant class to maintain One to One relation.
Step 5
Create applicant.hbm.xml
- <?xml version='1.0' encoding='UTF-8'?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.kb.model">
- <class name="Applicant" table="Applicant">
- <id name="applicantId" type="int">
- <column name="Applicant_Id"></column>
- <generator class="increment"></generator>
- </id>
- <property name="name" column="Name"></property>
- <property name="age" type="int" column="Age"></property>
- <property name="city" column="City"></property>
- <one-to-one name="passport" class="Passport" cascade="save-update"></one-to-one>
- </class>
- </hibernate-mapping>
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.kb.model"> <class name="Applicant" table="Applicant"> <id name="applicantId" type="int"> <column name="Applicant_Id"></column> <generator class="increment"></generator> </id> <property name="name" column="Name"></property> <property name="age" type="int" column="Age"></property> <property name="city" column="City"></property> <one-to-one name="passport" class="Passport" cascade="save-update"></one-to-one> </class> </hibernate-mapping>
In this mapping file,We have defined the Table mapping for Applicant class.
We have specified Primary key as applicantId and generator class as “increment” for automatic primary key generation.
We have defined one to one mapping with Passport entity using “one-to-one” tag.
We have also provided cascade attribute value as “save-update” which means whenever we save or update Applicant record it will also save or update the Passport record automatically.
Step 6
Create passport.hbm.xml
- <?xml version='1.0' encoding='UTF-8'?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.kb.model">
- <class name="Passport" table="Passport">
- <id name="passportId" type="int">
- <column name="Passport_Id" />
- <generator class="foreign">
- <param name="property">applicant</param>
- </generator>
- </id>
- <one-to-one name="applicant" class="Applicant"
- constrained="true"></one-to-one>
- <property name="passportNumber" column="Passport_Number"/>
- <property name="issuedDate" type="date" column="Issued_Date"/>
- <property name="expiryDate" type="date" column="Expiry_Date"/>
- </class>
- </hibernate-mapping>
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.kb.model"> <class name="Passport" table="Passport"> <id name="passportId" type="int"> <column name="Passport_Id" /> <generator class="foreign"> <param name="property">applicant</param> </generator> </id> <one-to-one name="applicant" class="Applicant" constrained="true"></one-to-one> <property name="passportNumber" column="Passport_Number"/> <property name="issuedDate" type="date" column="Issued_Date"/> <property name="expiryDate" type="date" column="Expiry_Date"/> </class> </hibernate-mapping>
In this mapping file,We have defined the Table mapping for Passport class.
We have specified Primary key as passportId and generator class as “foreign”.
Generator class “foreign” indicates that Primary key of Passport table will be coming from Applicant table and we have to use the property name as same as relation name which is “applicant”.
We have defined one to one mapping with Applicant entity using “one-to-one” tag.
We have also provided “constrained” as true which specifies that a foreign key constraint on the primary key of the mapped table and references the table of the associated class.
In other words constrained=true ensures that Applicant must exist for the passport record.
Step 7
Create hibernate.cfg.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <!-- Database connection properties -->
- <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
- <property name="connection.url">jdbc:mysql://localhost/javainsimpleway</property>
- <property name="connection.username">root</property>
- <property name="connection.password">root</property>
- <!-- JDBC connection pool (using the built-in) -->
- <property name="connection.pool_size">10</property>
- <!-- SQL dialect -->
- <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
- <!-- Disable the second-level cache -->
- <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
- <!-- Echo all executed SQL to stdout -->
- <property name="show_sql">true</property>
- <!-- Format the generated Sql -->
- <property name="format_sql">true</property>
- <!-- Dont Drop and re-create the database schema on startup,Just update it -->
- <property name="hbm2ddl.auto">update</property>
- <mapping resource="com/kb/mapping/applicant.hbm.xml"/>
- <mapping resource="com/kb/mapping/passport.hbm.xml"/>
- </session-factory>
- </hibernate-configuration>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection properties --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/javainsimpleway</property> <property name="connection.username">root</property> <property name="connection.password">root</property> <!-- JDBC connection pool (using the built-in) --> <property name="connection.pool_size">10</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Format the generated Sql --> <property name="format_sql">true</property> <!-- Dont Drop and re-create the database schema on startup,Just update it --> <property name="hbm2ddl.auto">update</property> <mapping resource="com/kb/mapping/applicant.hbm.xml"/> <mapping resource="com/kb/mapping/passport.hbm.xml"/> </session-factory> </hibernate-configuration>
We have defined all the database configuration in this file
hbm2ddl.auto property is defined in the config file which helps in automatic creation of tables in the database based on the mapping.
We have also provided the mapping xml file location using “mapping” tag.
Step 8
Create Hibernate util class
- package com.kb.util;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- public class HibernateUtil {
- private static final SessionFactory sessionFactory = buildSessionFactory();
- private static SessionFactory buildSessionFactory() {
- try {
- // Create the SessionFactory from hibernate.cfg.xml
- return new Configuration().configure().buildSessionFactory();
- } catch (Throwable ex) {
- // Make sure you log the exception to track it
- System.err.println("SessionFactory creation failed." + ex);
- throw new ExceptionInInitializerError(ex);
- }
- }
- public static SessionFactory getSessionFactory() {
- return sessionFactory;
- }
- public static void shutdown() {
- // Optional but can be used to Close caches and connection pools
- getSessionFactory().close();
- }
- }
package com.kb.util; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml return new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { // Make sure you log the exception to track it System.err.println("SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } public static void shutdown() { // Optional but can be used to Close caches and connection pools getSessionFactory().close(); } }
Step 9
Create main class to interact with DB
- package com.kb.db;
- import java.util.Calendar;
- import java.util.Date;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import com.kb.model.Applicant;
- import com.kb.model.Passport;
- import com.kb.util.HibernateUtil;
- public class Main {
- public static void main(String[] args) {
- // Get session factory using Hibernate Util class
- SessionFactory sf = HibernateUtil.getSessionFactory();
- // Get session from Sesson factory
- Session session = sf.openSession();
- // Begin transaction
- Transaction t = session.beginTransaction();
- //Create Applicant Model data
- Applicant applicant = new Applicant();
- applicant.setName("John");
- applicant.setAge(28);
- applicant.setCity("Newyork");
- //Create Passport Model data
- Passport passport = new Passport();
- passport.setPassportNumber("ABCDE1111Z");
- passport.setIssuedDate(new Date());
- Calendar date = Calendar.getInstance();
- date.setTime(new Date());
- date.add(Calendar.YEAR, 10);
- passport.setExpiryDate(date.getTime());
- applicant.setPassport(passport);
- passport.setApplicant(applicant);
- session.persist(applicant);
- // Commit the transaction and close the session
- t.commit();
- session.close();
- System.out.println("successfully persisted Applicant details");
- }
- }
package com.kb.db; import java.util.Calendar; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import com.kb.model.Applicant; import com.kb.model.Passport; import com.kb.util.HibernateUtil; public class Main { public static void main(String[] args) { // Get session factory using Hibernate Util class SessionFactory sf = HibernateUtil.getSessionFactory(); // Get session from Sesson factory Session session = sf.openSession(); // Begin transaction Transaction t = session.beginTransaction(); //Create Applicant Model data Applicant applicant = new Applicant(); applicant.setName("John"); applicant.setAge(28); applicant.setCity("Newyork"); //Create Passport Model data Passport passport = new Passport(); passport.setPassportNumber("ABCDE1111Z"); passport.setIssuedDate(new Date()); Calendar date = Calendar.getInstance(); date.setTime(new Date()); date.add(Calendar.YEAR, 10); passport.setExpiryDate(date.getTime()); applicant.setPassport(passport); passport.setApplicant(applicant); session.persist(applicant); // Commit the transaction and close the session t.commit(); session.close(); System.out.println("successfully persisted Applicant details"); } }
We have created one Applicant and associated a Passport to that Applicant.
We are persisting only Applicant but both Applicant and Passport will be saved into DB.
It’s because we have given cascade=save-update in applicant.hbm.xml file.
Step 10
Run the above class to check the output
Hibernate: create table Applicant ( Applicant_Id integer not null, Name varchar(255), Age integer, City varchar(255), primary key (Applicant_Id) ) Hibernate: create table Passport ( Passport_Id integer not null, Passport_Number varchar(255), Issued_Date date, Expiry_Date date, primary key (Passport_Id) ) Hibernate: alter table Passport add constraint FKh6nj623boddru6w09ftabw82g foreign key (Passport_Id) references Applicant (Applicant_Id) Hibernate: select max(Applicant_Id) from Applicant Hibernate: insert into Applicant (Name, Age, City, Applicant_Id) values (?, ?, ?, ?) Hibernate: insert into Passport (Passport_Number, Issued_Date, Expiry_Date, Passport_Id) values (?, ?, ?, ?) successfully persisted Applicant details
We can see that Create statement is executed for creating both Applicant and Passport tables.
We can see that Foreign key constraint is created on Passport table referencing the primary key of Applicant table..
2 insert statements are executed (one for Applicant and one for Passport).
Check Table in MYSQL console
E:\MySql_Install\bin
Mysql –u root –p
Enter password
Use javainsimpleway;
Select * from Applicant;
Select * from Passport;
We can see that same primary key is shared between Applicant and Passport table.