Sunday, May 3, 2015

Hibernate4 One-to-One Relationship Example Using Annotations

In this article we are going to create a project to implement step by step one-to-one association example using Annotations with Maven project.

OneToOne Relationship:
A one-to-one relationship occurs when one entity is related to exactly one occurrence in another entity. For example, we have a Employee and Address tables, Employee has its single Address and each Address belongs to unique Employee. 

We can associate entities through a one-to-one relationship using the @OneToOne annotation (javax.persistence.OneToOne).

There are three different ways to implement OneToOne Association. 
1. Either the associated entities share the same primary key values(Shared Primary Key association).
2. A foreign key is held by one of the entities (One-to-One foreign key association).
3. A association table is used to store the link between the 2 entities (Using a join table).

1) One-to-One association using shared primary keys:
A one to one shared primary key relationship would mean that a Employee table does not have a foreign key column to Address table, rather the Address table's primary key value is the same as Employee, and acts as a foreign key to the Employee table.

In order to use a one to one with a shared primary key, ids on both sides of the object need a @GeneratedValue. The owner can use a generic generator where it gets a fresh number every time, but the other side of the one to one needs a custom hibernate extension, which is from @GenericGenerator. In our example, Address will have the hibernate extension @GenericGenerator.
Employee.java

@Entity
@Table(name="Employee")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="employeeId")
private long id;

@OneToOne(mappedBy="employee", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Address address;
    // some more properties
 
    public Employee() {
super();
}
// setters and getters
}
Address.java

@Entity
@Table(name="Address")
@GenericGenerator(name="employee-primarykey", strategy="foreign", parameters=@Parameter(name="property", value="employee"))
public class Address implements Serializable {
@Id
@Column(name="addressId")
@GeneratedValue(generator="employee-primarykey")
private long addressId;

// some other properties

@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;

public Address() {
super();
}
// setters and getters
}

The @PrimaryKeyJoinColumn annotation does say that the primary key of the entity is used as the foreign key value to the associated entity.

Let us see the full example.

Tools and Technologies Used: 
1. Java 6 or Above Version 
2. Hibernate 4.3.7 Final 
3. MySQL5.6 
4. Maven 3.2.2 
5. Eclipse Luna
Project Structure: 
Step-1. Creating Database and Tables:
CREATE DATABASE `vara_softtech`;
use vara_softtech;

CREATE TABLE `employee` (
`employeeId` bigint(20) NOT NULL AUTO_INCREMENT,
`age` int(11) DEFAULT NULL,
`firstName` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
PRIMARY KEY (`employeeId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `address` (
`addressId` bigint(20) NOT NULL,
`city` varchar(255) DEFAULT NULL,
`houseNo` varchar(255) DEFAULT NULL,
`street` varchar(255) DEFAULT NULL,
PRIMARY KEY (`addressId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Step-2. Creating  Maven-Eclipse Project:
In Eclipse IDE, create a Maven project named Hibernate4_Association_Mapping with the above structure.
This project consists of the following files:
Hibernate Configuration file: hibernate.cfg.xml
POJO classes: Employee.java and Address.java
Util class: HibernateUtil.java
Client Program: Application.java
Maven project: pom.xml
Step-3. Adding the project dependencies into pom.xml file:
<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>com.varasofttech</groupId>
<artifactId>Hibernate4_Association_Mapping</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Association Mapping</name>
<dependencies>

<!-- Hibernate framework -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.7.Final</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>

<!-- My SQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
</project>

Step-4. Creating the Hibernate Configuration file hibernate.cfg.xml file:
<?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 Settings -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///vara_softtech</property>
<property name="hibernate.connection.username">varasofttech</property>
<property name="hibernate.connection.password">varasofttech</property>

<!-- Dialect class -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

<!-- Hibernate specific -->
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>

<!-- OneToOne Mapping -->
<mapping class="com.varasofttech.onetoone.Address" />
<mapping class="com.varasofttech.onetoone.Employee" />
</session-factory>
</hibernate-configuration>
Step-5. Creating the Hibernate Helper class HibernateUtil.java:
package com.varasofttech.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
/**
*
* @author Ranga Reddy
* @date Feb 24, 2015
* @version 1.0
* @description : HibernateUtil.java
*/

public class HibernateUtil {
private static SessionFactory sessionFactory = null;

public static SessionFactory getSessionFacoty() {
return buildSessionFactory();
}
private static SessionFactory buildSessionFactory() {
if (sessionFactory == null) {
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();

sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
return sessionFactory;
}
    public static void closeSessionFactory() {
if (sessionFactory != null)
sessionFactory.close();
            sessionFactory = null;
} }
Step-6. Creating the POJO classes Employee.java and Address.java:
package com.varasofttech.onetoone;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

/**
* @author Ranga Reddy
* @date Apr 20, 2015
* @version 1.0
* @description : Employee.java
*/


@Entity
@Table(name="Employee")
public class Employee implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="employeeId")
private long id;
@Column
private String firstName;
@Column
private String lastName;
@Column
private int age;

@OneToOne(mappedBy="employee", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Address address;

public Employee() {
super();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}

@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", age=" + age + "]";
}
}
package com.varasofttech.onetoone;

import java.io.Serializable;
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.Parameter;
import org.hibernate.annotations.GenericGenerator;
/**
* @author Ranga Reddy
* @date Apr 20, 2015
* @version 1.0
* @description : Address.java
*/

@Entity
@Table(name="Address")
@GenericGenerator(name="employee-primarykey", strategy="foreign", parameters=@Parameter(name="property", value="employee"))
public class Address implements Serializable {

@Id
@Column(name="addressId")
@GeneratedValue(generator="employee-primarykey")
private long addressId;
@Column
private String houseNo;
@Column
private String street;
@Column
private String city;

@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;

public Address() {
super();
}
public long getAddressId() {
return addressId;
}
public void setAddressId(long addressId) {
this.addressId = addressId;
}
public String getHouseNo() {
return houseNo;
}
public void setHouseNo(String houseNo) {
this.houseNo = houseNo;
}
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 Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Override
public String toString() {
return "Address [addressId=" + addressId + ", houseNo=" + houseNo
+ ", street=" + street + ", city=" + city + "]";
}
}
Step-7. Creating the Client Application Application.java:
package com.varasofttech.onetoone;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.varasofttech.util.HibernateUtil;

/**
* @author Ranga Reddy
* @date Apr 20, 2015
* @version 1.0
* @description : Application.java
*/

public class Application {
public static void main(String[] args) {
Employee employee = new Employee();
employee.setFirstName("Ranga");
employee.setLastName("Reddy");
employee.setAge(27);

Address address = new Address();
address.setCity("Bangalore");
address.setHouseNo("12345");
address.setStreet("SRI Nagar");

employee.setAddress(address);
address.setEmployee(employee);

SessionFactory sessionFactory = HibernateUtil.getSessionFacoty();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
long employeeId = (Long) session.save(employee);

transaction.commit();
session.close();

sessionFactory = HibernateUtil.getSessionFacoty();
session = sessionFactory.openSession();
Employee emp = (Employee) session.get(Employee.class, employeeId);
System.out.println("Employee Details :");
System.out.println(emp);

System.out.println("Employee Address Details :");
System.out.println(emp.getAddress());
session.close();
}
}
Step-8. Run the client application
Hibernate: insert into Employee (age, firstName, lastName) values (?, ?, ?)
Hibernate: insert into Address (city, houseNo, street, addressId) values (?, ?, ?, ?)
Hibernate: select employee0_.employeeId as employee1_1_0_, employee0_.age as age2_1_0_, employee0_.firstName as firstNam3_1_0_, employee0_.lastName as lastName4_1_0_ from Employee employee0_ where employee0_.employeeId=?
Hibernate: select address0_.addressId as addressI1_0_0_, address0_.city as city2_0_0_, address0_.houseNo as houseNo3_0_0_, address0_.street as street4_0_0_, employee1_.employeeId as employee1_1_1_, employee1_.age as age2_1_1_, employee1_.firstName as firstNam3_1_1_, employee1_.lastName as lastName4_1_1_ from Address address0_ left outer join Employee employee1_ on address0_.addressId=employee1_.employeeId where address0_.addressId=?
Employee Details :
Employee [id=1, firstName=Ranga, lastName=Reddy, age=27]
Employee Address Details :
Address [addressId=1, houseNo=12345, street=SRI Nagar, city=Bangalore]
One-to-One with a shared primary key saves a column in the database and usually forces a bidirectional relationship through an ORM such as hibernate.

Happy Coding!!!

0 comments: