How to create one to one relationship in Hibernate 4 with Annotation?

Annotations is now widely used in the development of Java programming and Hibernate also supports this. Programmers can take the advantages of this for developing applications quickly. This tutorial teaches you how to develop relationship in Hibernate using annotations.

How to create one to one relationship in Hibernate 4 with Annotation?

How to create one to one relationship in Hibernate 4 with Annotation?

In this tutorial we are developing an application in Hibernate 4 to create one-to-one mapping. In this example we have two entities worker and workerdetails. These two entities are mapped to each other through one-to-one mapping and we can use the feature of Hibernate while saving the entities.

This tutorial is using Java 5 annotations for defining the mapping between these two domain entities. We have used MySQL database as backend server but you can also update Hibernate configuration to use other database database of your choice. MySQL is easily to install and small server but its powerful enough to manage huge databases.

Why use annotations in Hibernate?

Annotations was first introduced in Java 5 and now this features is one of most widely used features in Java programming. Hibernate 4 framework increases the productivity of the developers working on development of persistence layer. Annotations further added simplicity in programming which makes coding much easier and hence it increases the productivity of the developer.

Developers working on Hibernate framework finds annotations much useful while making changes or doing the maintenance of the software. For example when there is any change in database structure due to change in business logic or new requirement, developers can quickly change the annotated entity class. This makes the process of application maintenance much easier as there is no requirement of changing the model class and mapping information separately.

What is one to one mapping?

One to one mapping is the mapping in which exactly one record from Table A maps to one record in Table B and vice versa.

In this case record of one table have only one related record in the other table. In this tutorial we have use two entities worker and workerdetail. One record in worker table maps to only one record in the workerdetail table.

Simply, one record in the worker table maps to only one address record in the workerdetail table.

Example of One to One mapping

In this example we will add the data into two tables into the database and data in both the tables will be inserted using one save statement. Both the table worker and workerdetail is related with each other through foreign key worker_id field. In the example given below, Hibernate 4 annotation based one to one mapping is accomplished.

We have used the Annotated model class in the the example code which simplifies the development work as explained above.

Here is the structure of the project which shows the required jar files:

The sql query used to create the tables worker and workerdetail is given below :

CREATE TABLE `worker` ( 
`worker_id` bigint(10) NOT NULL auto_increment, 
`firstname` varchar(50) default NULL, 
`lastname` varchar(50) default NULL, 
`birth_date` date NOT NULL, 
`cell_phone` varchar(15) NOT NULL, 
PRIMARY KEY (`worker_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 


CREATE TABLE `workerdetail` ( 
`worker_id` bigint(20) NOT NULL auto_increment, 
`street` varchar(50) default NULL, 
`city` varchar(50) default NULL, 
`state` varchar(50) default NULL, 
`country` varchar(50) default NULL, 
PRIMARY KEY (`worker_id`), 
CONSTRAINT `FK_workerdetail` FOREIGN KEY (`worker_id`) REFERENCES `worker` (`worker_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Source Code:

hibernate.cfg.xml ( /src/hibernate.cfg.xml )

This file is used to define the Hibernate session factory by providing the database url and connection details. Here is the full source code used in the project:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://192.168.10.13:3306/anky</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>

<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">validate</property>

<mapping class="net.roseindia.WorkerDetail"/>
<mapping class="net.roseindia.Worker"/>

</session-factory>
</hibernate-configuration>

Worker.java ( /src/net/roseindia/Worker.java )

The Worker.java is the Entity(Model) class in the project which maps to "worker" table. It defines the mapping via @OneToOne annotation. Here is the source code of Worker.java model class:

package net.roseindia;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "worker")
public class Worker {

@Id
@GeneratedValue
@Column(name = "worker_id")
private Long workerId;



@Column(name = "firstname")
private String firstname;

@Column(name = "lastname")
private String lastname;

@Column(name = "birth_date")
private Date birthDate;

@Column(name = "cell_phone")
private String cellphone;

@OneToOne(mappedBy = "worker", cascade = CascadeType.ALL)
private WorkerDetail workerDetail;

public Worker() {

}

public Worker(String firstname, String lastname, Date birthdate,
String phone) {
this.firstname = firstname;
this.lastname = lastname;
this.birthDate = birthdate;
this.cellphone = phone;

}

public Long getWorkerId() {
return workerId;
}

public void setWorkerId(Long workerId) {
this.workerId = workerId;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getLastname() {
return lastname;
}

public void setLastname(String lastname) {
this.lastname = lastname;
}

public Date getBirthDate() {
return birthDate;
}

public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}

public String getCellphone() {
return cellphone;
}

public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}

public WorkerDetail getWorkerDetail() {
return workerDetail;
}

public void setWorkerDetail(WorkerDetail workerDetail) {
this.workerDetail = workerDetail;
}
}

WorkerDetail.java( /src/net/roseindia/WorkerDetail.java )

The WorkerDetail.java is second Entity in the project which maps to "workerdetailtable" and participate in one-to-one mapping. Here is the full source code of the Entity class:

package net.roseindia;

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="workerdetail")
public class WorkerDetail {
@Id
@Column(name="worker_id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="worker"))
private Long workerId;

@Column(name="street")
private String street;

@Column(name="city")
private String city;

@Column(name="state")
private String state;

@Column(name="country")
private String country;

@OneToOne
@PrimaryKeyJoinColumn
private Worker worker;

public WorkerDetail() {

}

public WorkerDetail(String street, String city, String state, String country) {
this.street = street;
this.city = city;
this.state = state;
this.country = country;
}

public Long getWorkerId() {
return workerId;
}

public void setWorkerId(Long workerId) {
this.workerId = workerId;
}

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public Worker getWorker() {
return worker;
}

public void setWorker(Worker worker) {
this.worker = worker;
}
}

ManageWorker.java ( /src/net/roseindia/ManageWorker.java )

This class is the actual program in the application which test the Hibernate code and insert the data into worker and workerdetails tables. Here is the full source code of the example program:

package net.roseindia;

import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class ManageWorker {
private static SessionFactory sf;
private static ServiceRegistry serviceRegistry;

@SuppressWarnings("unchecked")
public static void main(String[] args) {
try {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()).buildServiceRegistry();
sf = configuration.buildSessionFactory(serviceRegistry);
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
System.out.println("Example : Hibernate One to One Mapping using Annotation ");
Session session = sf.openSession();
session.beginTransaction();

WorkerDetail workerDetail = new WorkerDetail("Lake Town", "Kolkata",
"West Bengal", "India");

//For passing Date of birth as String
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dob=null;
try {
dob = sdf.parse("1987-05-21");
} catch (ParseException e) {
e.printStackTrace();
}

Worker worker = new Worker("Sushmita", "Dasgupta",dob,
"919595959595");
worker.setWorkerDetail(workerDetail);
workerDetail.setWorker(worker);

session.save(worker);

List<Worker> workerList = session.createQuery("from Worker").list();
for (Worker work1 : workerList) {
System.out.println(work1.getFirstname() + " , "
+ work1.getLastname() + ", "
+ work1.getWorkerDetail().getState());
}

session.getTransaction().commit();
session.close();

}
}

Output of the program

You can run the program from Eclipse itself and it will produce similar output:

Example : Hibernate One to One Mapping using Annotation 
Hibernate: insert into worker (birth_date, cell_phone, firstname, lastname) values (?, ?, ?, ?)
Hibernate: select worker0_.worker_id as worker1_1_, worker0_.birth_date as birth2_1_, worker0_.cell_phone as cell3_1_, worker0_.firstname as firstname1_, worker0_.lastname as lastname1_ from worker worker0_
Sushmita , Dasgupta, West Bengal
Hibernate: insert into workerdetail (city, country, state, street, worker_id) values (?, ?, ?, ?, ?)

In worker table, you should get the following record :

In workerdetail table you will get the following record :

Download Source Code

Check 1000s of tutorial of Hibernate ORM framework.