Wednesday, October 14, 2015

Hibernate Uni-directional One-to-One Mapping with Annotation

There are two Hibernate mapping directions.
  • Bi-directional mapping
 Here both student and address objects have reference to each other, thus, address object can retrieve student data.

  • Uni-directional mapping
              Here the relationship is kept only on one side. You can directly retrieve data only from one side.
              Lets consider one to one relationship

                   One student dwells in one Address.
                   One address can be occupied by only one student

    if student domain object has a reference to an address object, but address  domain object does not have a reference to the student object, only from a student object you can retrieve address data.


To create a uni-directional mapping using JPA annotation for above relation, we should identify which relation should contain the foreign key. Lets say Student relation contains the foreign key. Therefore, we need a reference to the address and address class will not have any reference

Address class looks like this

package com.sajith.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Address domain object
 */

@Entity
@Table(name = "ADDRESS")
public class Address {

 @Id
 @Column(name = "ADDRESS_NO")
 private int addressNo;

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

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

 public int getAddressNo() {
  return addressNo;
 }

 public void setAddressNo(int addressNo) {
  this.addressNo = addressNo;
 }

 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;
 }

}
 
 
In this class addressNo field represents primary key table column ADDRESS_NO. This column is the foreign key column in STUDENT table. To represent this relationship in Student class will contain the address as a field and annotations will be used to indicate that it is the mapping field and hold the foreign key.

Student class as follow
package com.sajith.domain;

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

/**
 * Student Domain class
 * 
 */

@Entity
@Table(name = "STUDENT")
public class Student {

 private int studentId;

 private String studentName;

 private Address studentAddress;

 @Id
 @Column(name = "ID")
 @GeneratedValue
 public int getStudentId() {
  return studentId;
 }

 public void setStudentId(int studentId) {
  this.studentId = studentId;
 }

 @Column(name = "NAME")
 public String getStudentName() {
  return studentName;
 }

 public void setStudentName(String studentName) {
  this.studentName = studentName;
 }

 @OneToOne(cascade = CascadeType.ALL)
 @JoinColumn(name = "ADDRESS_NO")
 public Address getStudentAddress() {
  return studentAddress;
 }

 public void setStudentAddress(Address studentAddress) {
  this.studentAddress = studentAddress;
 }

}

@OneToOne - States the relationship type
   CascadeType.ALL - States that when changes happen to Student, the corresponding Address should be   changed as well
E.g:  If student is deleted his address should be deleted as well.
@JoinColumn:  States the foreign key column

Get the Hibernate configuration file from my previous Hibernate post and adds the Address class
 <mapping class="com.sajith.domain.Address"/>

Hibernate Util class


package com.sajith.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

 private static final SessionFactory sessionFactory = buildSessionFactory();

 private static ServiceRegistry serviceRegistry;

 private static SessionFactory buildSessionFactory() {

  Configuration configuration = new Configuration();
  configuration.configure();
  serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
    configuration.getProperties()).build();

  return configuration.buildSessionFactory(serviceRegistry);

 }

 public static SessionFactory getSessionFactory() {
  return sessionFactory;
 }

 public static void shutdown() {
  // Close caches and connection pools
  getSessionFactory().close();
 }

} 

Main App class
package com.sajith;

import org.hibernate.Session;

import com.sajith.domain.Address;
import com.sajith.domain.Student;
import com.sajith.util.HibernateUtil;

public class App {

 
 public static void main(String[] args) {
  
 
  Session session = HibernateUtil.getSessionFactory().openSession();

  session.beginTransaction();
   
  Student student1 = new Student();
  
  Address address  = new Address();
  
  address.setAddressNo(2);
  address.setCity("Colombo");
  address.setStreet("Horton Place");
  
  
  student1.setStudentId(3);
                student1.setStudentName("Sanya Fernando");
                student1.setStudentAddress(address);
 
 

  session.save(student1);
  session.getTransaction().commit();
  
  System.exit(0);
 }
 
}

As you can see we create a Student instance and assign an address.
Create the tables like following.

Address table



Student table



If you execute the App file, output will be








No comments: