Thursday, 15 March 2018

Hibernate One-to-One Mapping Example Using Annotations

               In the previous post, we learned about Hibernate Annotations with detailed explanations. In this post, we will learn what a one-to-one relationship is in Hibernate and how to implement it using annotations.

To demonstrate this relationship, we will use two entity classes, Student and Address, and establish a one-to-one association between them.

In this example, we will implement the one-to-one relationship using a foreign key association. Another way to implement a one-to-one relationship is by using a primary key association with the @PrimaryKeyJoinColumn annotation.

In the example below, the Student table contains a foreign key column (address_id) that references the primary key (address_id) of the Address table.


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


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 + "]";
        }
 
}



Create Hibernate Configuration file:-

           We need to configure Hibernate with the database connection details and specify the database dialect so that Hibernate can generate SQL statements specific to the selected database.

We define all of this configuration in the hibernate.cfg.xml file. Create this file with the following content and save it in the 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 – Specifies the database dialect that Hibernate uses to generate SQL statements specific to the selected database.

  • driver_class – Specifies the JDBC driver class that Hibernate uses to establish a connection to the database.

  • show_sql – Instructs Hibernate to log all generated SQL statements to the console.

  • format_sql – Instructs Hibernate to format the generated SQL statements, making them easier to read.



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

1 comment:

  1. Waoo Awesome content posting,Many developers would agree that hibernate is difficult and complex whereas hibernate is simple and so more productive,This site is so amazing.This sites gives good knowledge of hibernate.

    ReplyDelete