One to One Annotation Mapping in Hibernate
Let us understand about One to One Annotation 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>OneToOneAnnotation</groupId>
- <artifactId>OneToOneAnnotation</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>OneToOneAnnotation</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/org.hibernate/hibernate-annotations -->
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-annotations</artifactId>
- <version>3.5.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>OneToOneAnnotation</groupId> <artifactId>OneToOneAnnotation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>OneToOneAnnotation</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/org.hibernate/hibernate-annotations --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-annotations</artifactId> <version>3.5.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;
- import javax.persistence.CascadeType;
- 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;
- @Entity
- @Table(name="Applicant")
- public class Applicant {
- @Id
- @GeneratedValue(strategy = GenerationType.SEQUENCE)
- @Column(name = "Applicant_Id")
- private int applicantId;
- @Column(name = "name")
- private String name;
- @Column(name="Age")
- private int age;
- @Column(name="city")
- private String city;
- @OneToOne(mappedBy="applicant", cascade=CascadeType.ALL)
- 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; import javax.persistence.CascadeType; 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; @Entity @Table(name="Applicant") public class Applicant { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name = "Applicant_Id") private int applicantId; @Column(name = "name") private String name; @Column(name="Age") private int age; @Column(name="city") private String city; @OneToOne(mappedBy="applicant", cascade=CascadeType.ALL) 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; } }
We have specified Primary key as applicantId and generator class as “sequence” for automatic primary key generation.
We have defined one to one mapping with Passport entity using OneToOne annotation
We have also provided cascade attribute value as “All” which means whenever we any operations like save or update on Applicant record it will also perform the same operation on Passport record automatically.
Step 4
Create Passport class
- package com.kb.model;
- import java.util.Date;
- 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="Passport")
- public class Passport {
- @Id
- @GeneratedValue(generator="gen")
- @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property",
- value="applicant"))
- @Column(name = "Passport_Id")
- private int passportId;
- @Column(name = "Passport_Number")
- private String passportNumber;
- @Column(name = "Issued_Date")
- private Date issuedDate;
- @Column(name = "Expiry_Date")
- private Date expiryDate;
- @OneToOne
- @PrimaryKeyJoinColumn
- 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; 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="Passport") public class Passport { @Id @GeneratedValue(generator="gen") @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="applicant")) @Column(name = "Passport_Id") private int passportId; @Column(name = "Passport_Number") private String passportNumber; @Column(name = "Issued_Date") private Date issuedDate; @Column(name = "Expiry_Date") private Date expiryDate; @OneToOne @PrimaryKeyJoinColumn 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; } }
We have specified Primary key as “passportId” and generator strategy as “foreign”.
We have defined one to one mapping with Applicant entity using “one-to-one” tag.
@PrimaryKeyJoinColumn – Specifies a primary key column that is used as a foreign key to join to another table.
In our case, it specifies Primary key of Applicant table to be used as join column to establish the mapping.
Step 5
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 class="com.kb.model.Applicant" />
- <mapping class="com.kb.model.Passport" />
- </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 class="com.kb.model.Applicant" /> <mapping class="com.kb.model.Passport" /> </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 6
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 7
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 is because we have given cascade=All in Applicant class.
Step 8
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.