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

OneToOne_ERD

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

OneToOneAnnotationProjStructure

Step 2

Update pom.xml with Hibernate and Mysql dependencies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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;

OneToOneAnnotationOutput

We can see that same primary key is shared between Applicant and Passport table.

Download this project OneToOneAnnotation.zip

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on