Thursday 15 March 2018

Hibernate One to One Mapping Example - Annotation based

              In previous post, we learned about Hibernate Annotations with explanation. In this we will see what is hibernate one to one relationship and how to implement it using Annotatons. We will demonstrate the relationship by taking two model classes Student  and  Address and try to establish a one to one relationship in between them.

              In this example, shown one to one relationship using foreign key association. Another way is using primary key association using @PrimaryKeyJoinColumn. In the below example Student table has foreign key column(address_id) references the primary key of Address Table (Primary key is address_id) .

onetoone mapping in hibernate
Create Database Tables :-

          Using MySQL database, creating two tables student and address. Student table has one foreign key constraint i.e address_id. (You can use any database as your wish).


create table STUDENT (
   student_id BIGINT NOT NULL AUTO_INCREMENT,
   address_id BIGINT NOT NULL,
   first_name VARCHAR(30) NOT NULL,
   last_name  VARCHAR(30) NOT NULL,
   section    VARCHAR(30) NOT NULL,
   PRIMARY KEY (student_id),
   CONSTRAINT student_address FOREIGN KEY (address_id) REFERENCES ADDRESS (address_id)
);

create table ADDRESS (
   address_id BIGINT NOT NULL AUTO_INCREMENT,
   street VARCHAR(30) NOT NULL,
   city  VARCHAR(30) NOT NULL,
   country  VARCHAR(30) NOT NULL,
   PRIMARY KEY (address_id)
);


Next step,
Create Model Classes:-

      Model class Student & Address are simple POJO class which is annotated with JPA annotations to map it to a database tables

Student.java,

package com.testapp.hibernate.model;
 
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;
 
@Entity
@Table(name = "student")
public class Student {
 
      @Id
      @GeneratedValue
      @Column(name = "student_id")
      private long id;
 
      @Column(name = "first_name")
      private String firstName;
 
      @Column(name = "last_name")
      private String lastName;
 
      @Column(name = "section")
      private String section;
 
      @OneToOne
      @JoinColumn(name="address_id")
      private Address address;
 
 
      public Student() {
 
      }
 
      public Student(String firstName, String lastName, String section) {
          this.firstName = firstName;
          this.lastName = lastName;
          this.section = section;
      }
 
      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 String getSection() {
          return section;
      }
 
      public void setSection(String section) {
          this.section = section;
      }
 
      public Address getAddress() {
          return address;
      }
 
      public void setAddress(Address address) {
          this.address = address;
      }
 
      @Override
      public String toString() {
          return "Student [id=" + id + ", firstName=" + firstName + ", lastName="
                + lastName + ", section=" + section + ", address=" + address
                + "]";
      }
}

       In this example I used Unidirectional Mapping i.e it will provide navigational access only to one direction(i.e ). For this I didn't use @OneToOne annotation in Address entity.

Address.java,

package com.testapp.hibernate.model;

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

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

        @Id 
        @GeneratedValue
        @Column(name = "address_id")
        private long id;

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

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

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

        public Address() {

        }

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

        public long getId() {
             return id;
        }

        public void setId(long id) {
             this.id = id;
        }

        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 getCountry() {
             return country;
        }

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

        @Override
        public String toString() {
             return "Address [id=" + id + ", street=" + street + ", city=" + city
              + ", country=" + country + "]";
        }
 
}



Next step,
Create Hibernate Configuration file:-

          We need to inform hibernate about how to connect to database, which database dialect we will be using so that hibernate can generate the instruction specific to that database.

We define all these information in hibernate.cfg.xml. Create this file with below content and save it in src/main/resources folder.

hibernate.cfg.xml,


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/testapp</property>
        <property name="show_sql">true</property>
        <property name="format_sql">false</property>
        <mapping class="com.testapp.hibernate.model.Student"/>
        <mapping class="com.testapp.hibernate.model.Address"/>
    </session-factory>
</hibernate-configuration>

dialect - This property makes Hibernate generate the appropriate SQL for the chosen database.
driver_class - This defines the database specific driver hibernate will use to make connection.
show_sql - It will instruct hibernate to log all the statements on console.
format_sql - It will instructs it to display properly formatted sql.


Next step,
Create Hibernate Utility Class,

HibernateUtil.java,

package com.testapp.hibernate;
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
 
public class HibernateUtil {
     
    private static final SessionFactory sessionFactory;
     
    static{
        try{
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
 
        }catch (Throwable ex) {
            System.err.println("Session Factory can not be created." + ex);
            throw new ExceptionInInitializerError(ex);
        }   
    }
     
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
     
}


Execute Main Class:--

Main Class to run and execute the insert and fetch operations,
HibernateApp.java,


package com.testapp.hibernate;
 
import java.util.List;
 
import org.hibernate.Session;
 
import com.testapp.hibernate.model.Address;
import com.testapp.hibernate.model.Student;
 
public class HibernateApp {
     
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
 
        Student student = new Student("Mahesh","Patil","A");
        Address address = new Address("#12, 12th E Main, Madiwala","Bangalore","India");
         
         
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
 
        session.persist(address);
        student.setAddress(address);
        session.persist(student);
 
        List<Student> students = (List<Student>)session.createQuery("from Student ").list();
        for(Student st: students){
            System.out.println("Student Details : "+st);
        }
         
        session.getTransaction().commit();
        session.close();  
    }
 
}

Execute the above code,

Output :--Hibernate: insert into ADDRESS (CITY, COUNTRY, STREET) values (?, ?, ?)
                  Hibernate: insert into STUDENT (ADDRESS_ID, FIRST_NAME, LAST_NAME,                                    SECTION) values (?, ?, ?, ?)
               
                  Hibernate: select student0_.STUDENT_ID as STUDENT_1_1_,student0_.ADDRESS_ID as ADD5_1_, student0_.FIRST_NAME as FIRST_NA2_1_, student0_.LAST_NAME as LAST_NAM3_1_, student0_.SECTION as SECTION4_1_ from STUDENT student0_

                 Student Details : Student [id=1, firstName=Mahesh, lastName=Patil, section=A, address=Address [id=1, street=#12, 12th E Main, Madiwala, city=Bangalore, country=India]]


Related Post:--
1) Advantages of Hibernate over JDBC
2) What are the Core Interfaces of Hibernate framework ?
3) Hibernate - JPA Annotations with explanation
4) Spring MVC with Hibernate CRUD Example

No comments:

Post a Comment