Examples illustrate many to one and one to many mappings in the Hibernate framework for Java

  • 2020-04-01 04:33:25
  • OfStack

Many-to-one mapping
Many-to-one associations are the most common association relationships, where an object can be associated with more than one object. For example, an identical address object can be associated with an object for more than one employee.

Define RDBMS tables:
Consider a case where we need the EMPLOYEE records to be stored in the EMPLOYEE table, which will have the following structure:


create table EMPLOYEE (
  id INT NOT NULL auto_increment,
  first_name VARCHAR(20) default NULL,
  last_name VARCHAR(20) default NULL,
  salary   INT default NULL,
  address  INT NOT NULL,
  PRIMARY KEY (id)
);

In addition, many employees can have the same address, so this association can be rendered using many one-to-one associations. We will store address related information in a separate table with the following structure:


create table ADDRESS (
  id INT NOT NULL auto_increment,
  street_name VARCHAR(40) default NULL,
  city_name VARCHAR(40) default NULL,
  state_name VARCHAR(40) default NULL,
  zipcode VARCHAR(10) default NULL,
  PRIMARY KEY (id)
);

At the same time, create the RBDMS tables and prepare them for the next implementation.

Define POJO classes:
Let's implement a POJO class EMPLOYEE that will be used to hold variables with the EMPLOYEE table's object and its address type.


import java.util.*;

public class Employee{
  private int id;
  private String firstName; 
  private String lastName;  
  private int salary;
  private Address address;

  public Employee() {}
  public Employee(String fname, String lname, 
          int salary, Address address ) {
   this.firstName = fname;
   this.lastName = lname;
   this.salary = salary;
   this.address = address;
  }
  public int getId() {
   return id;
  }
  public void setId( int id ) {
   this.id = id;
  }
  public String getFirstName() {
   return firstName;
  }
  public void setFirstName( String first_name ) {
   this.firstName = first_name;
  }
  public String getLastName() {
   return lastName;
  }
  public void setLastName( String last_name ) {
   this.lastName = last_name;
  }
  public int getSalary() {
   return salary;
  }
  public void setSalary( int salary ) {
   this.salary = salary;
  }

  public Address getAddress() {
   return address;
  }
  public void setAddress( Address address ) {
   this.address = address;
  }
}

We need to define the corresponding address table so that the address object can store and retrieve another POJO class in the address table.


import java.util.*;

public class Address{
  private int id;
  private String street;   
  private String city;   
  private String state;  
  private String zipcode; 

  public Address() {}
  public Address(String street, String city, 
         String state, String zipcode) {
   this.street = street; 
   this.city = city; 
   this.state = state; 
   this.zipcode = zipcode; 
  }
  public int getId() {
   return id;
  }
  public void setId( int 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 getState() {
   return state;
  }
  public void setState( String state ) {
   this.state = state;
  }
  public String getZipcode() {
   return zipcode;
  }
  public void setZipcode( String zipcode ) {
   this.zipcode = zipcode;
  }
  
}

Define Hibernate mapping file:
Develop our mapping file that tells Hibernate how to define classes that map to database tables. < Many - to - one> The proceed element will be used to define the rule establishing a many-to-one relationship between the Employee and Address entities.


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
  <class name="Employee" table="EMPLOYEE">
   <meta attribute="class-description">
     This class contains the employee detail. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <property name="firstName" column="first_name" type="string"/>
   <property name="lastName" column="last_name" type="string"/>
   <property name="salary" column="salary" type="int"/>
   <many-to-one name="address" column="address" 
    class="Address" not-null="true"/>
  </class>

  <class name="Address" table="ADDRESS">
   <meta attribute="class-description">
     This class contains the address detail. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <property name="street" column="street_name" type="string"/>
   <property name="city" column="city_name" type="string"/>
   <property name="state" column="state_name" type="string"/>
   <property name="zipcode" column="zipcode" type="string"/>
  </class>

</hibernate-mapping>

Format in the mapping file that should be saved. Classname> . HBM. XML. Save the file employee.hbm.xml in the mapping file. Most of the mapping details are already familiar, but let's look again at all the elements in the mapping file:

Mapping documents are available with < Hibernate - mapping> Contains 2 < for each class; Class> XML document for the root element of the element.

< Class> The element is used to define a database table specific mapping from a Java class. The Java class name is specified using the name attribute of the class element and the database table name using the table attribute.

< Meta> The element is an optional element that can be used to create a description of the class.

< Id> The element maps the unique ID attribute in the class to the primary key of the database table. The name attribute of the id element refers to the class of the attribute and the column attribute refers to the column in the database table. The type attribute holds the Hibernate mapping type that will be converted from Java to SQL data type.

Inside the id element < Generator> The element is used to automatically generate primary key values. Set the class attribute of the generated element to native to allow Hibernate to pick up whether it's identity, sequence, or hilo's algorithm to create the primary key based on the underlying database's supporting capabilities.

< Property> The element is used to map attributes of a Java class to columns in a database table. The name attribute of the element refers to the class of the attribute and the column attribute refers to the column in the database table. The type attribute holds the Hibernate mapping type that will be converted from Java to SQL data type.

< Many - to - one> The carry element is used to set the relationship between the EMPLOYEE and address entities. The name property is set to the variable defined in the parent class, which in our case is the address. The column attribute is used for the column name of the set of EMPLOYEE in the parent table.

Finally, we will create the main () method of the application class to run the application. We'll use the application to save some employees along with their addresses, and then we'll request records on CRUD operations.


import java.util.*;
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
  private static SessionFactory factory; 
  public static void main(String[] args) {
   try{
     factory = new Configuration().configure().buildSessionFactory();
   }catch (Throwable ex) { 
     System.err.println("Failed to create sessionFactory object." + ex);
     throw new ExceptionInInitializerError(ex); 
   }
   ManageEmployee ME = new ManageEmployee();

   
   Address address = ME.addAddress("Kondapur","Hyderabad","AP","532");

   
   Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, address);

   
   Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, address);

   
   ME.listEmployees();

   
   ME.updateEmployee(empID1, 5000);

   
   ME.deleteEmployee(empID2);

   
   ME.listEmployees();

  }

  
  public Address addAddress(String street, String city, 
               String state, String zipcode) {
   Session session = factory.openSession();
   Transaction tx = null;
   Integer addressID = null;
   Address address = null;
   try{
     tx = session.beginTransaction();
     address = new Address(street, city, state, zipcode);
     addressID = (Integer) session.save(address); 
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
   return address;
  }

  
  public Integer addEmployee(String fname, String lname, 
               int salary, Address address){
   Session session = factory.openSession();
   Transaction tx = null;
   Integer employeeID = null;
   try{
     tx = session.beginTransaction();
     Employee employee = new Employee(fname, lname, salary, address);
     employeeID = (Integer) session.save(employee); 
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
   return employeeID;
  }

  
  public void listEmployees( ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     List employees = session.createQuery("FROM Employee").list(); 
     for (Iterator iterator = 
              employees.iterator(); iterator.hasNext();){
      Employee employee = (Employee) iterator.next(); 
      System.out.print("First Name: " + employee.getFirstName()); 
      System.out.print(" Last Name: " + employee.getLastName()); 
      System.out.println(" Salary: " + employee.getSalary());
      Address add = employee.getAddress();
      System.out.println("Address ");
      System.out.println(" Street: " + add.getStreet());
      System.out.println(" City: " + add.getCity());
      System.out.println(" State: " + add.getState());
      System.out.println(" Zipcode: " + add.getZipcode());
     }
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
  }
  
  public void updateEmployee(Integer EmployeeID, int salary ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     Employee employee = 
          (Employee)session.get(Employee.class, EmployeeID); 
     employee.setSalary( salary );
     session.update(employee);
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
  }
  
  public void deleteEmployee(Integer EmployeeID){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     Employee employee = 
          (Employee)session.get(Employee.class, EmployeeID); 
     session.delete(employee); 
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
  }
}

Compile and execute:
Here are the steps to compile and run the above application. Be sure to set the PATH and CLASSPATH appropriately before compiling and executing.

The configuration section in the create hibernate.cfg.xml configuration file explains. Create the employee.hbm.xml mapping file, as shown in the figure above. Create the employee.java source file, as shown in the figure above, and compile it. Create the address.java source file, as shown in the figure above, and compile it. Create the manageemployee.java source file, as shown in the figure above, and compile it. Execute the ManageEmployee binary to run the program.

Get the following results on the screen, and the records will be created in both the employee and address tables.


$java ManageEmployee

.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Manoj Last Name: Kumar Salary: 4000
Address
    Street: Kondapur
    City: Hyderabad
    State: AP
    Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
    Street: Kondapur
    City: Hyderabad
    State: AP
    Zipcode: 532
First Name: Manoj Last Name: Kumar Salary: 5000
Address
    Street: Kondapur
    City: Hyderabad
    State: AP
    Zipcode: 532

If you check the employee and address lists, you should record:


mysql> select * from EMPLOYEE;

+----+------------+-----------+--------+---------+
| id | first_name | last_name | salary | address |
+----+------------+-----------+--------+---------+
| 1 | Manoj   | Kumar   |  5000 | 5    |
+----+------------+-----------+--------+---------+
1 row in set (0.00 sec)


mysql> select * from ADDRESS;

+----+-------------+-----------+------------+---------+
| id | street_name | city_name | state_name | zipcode |
+----+-------------+-----------+------------+---------+
| 1 | Kondapur  | Hyderabad | AP     | 532   |
+----+-------------+-----------+------------+---------+
1 row in set (0.00 sec)


One-to-one Many mapping
A one-to-many mapping can be implemented using a set of Java collections that do not contain any repeating elements. We've seen how to Set up a mapping Set in Hibernate, so if you've learned how to Set up a collection (Set) mapping, all Settings can be used for one-to-many mapping.

The collection is mapped to the mapping table. Set> Element and is initialized in the java.util.hashset. You can use Set collections in classes that have elements in the collection that do not need to be repeated.
RDBMS tables and POJO classes as defined in the above example,
Define Hibernate mapping file:
Let's instruct Hibernate how to define a class that maps to a mapping file for a database table.


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
  <class name="Employee" table="EMPLOYEE">
   <meta attribute="class-description">
     This class contains the employee detail. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <set name="certificates" cascade="all">
     <key column="employee_id"/>
     <one-to-many class="Certificate"/>
   </set>
   <property name="firstName" column="first_name" type="string"/>
   <property name="lastName" column="last_name" type="string"/>
   <property name="salary" column="salary" type="int"/>
  </class>

  <class name="Certificate" table="CERTIFICATE">
   <meta attribute="class-description">
     This class contains the certificate records. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <property name="name" column="certificate_name" type="string"/>
  </class>

</hibernate-mapping>

Format in the mapping file that should be saved. Classname> . HBM. XML. We save the file employee.hbm.xml in the mapping file. You're already familiar with most of the mapping details, but let's look again at all the elements in the mapping file:

Mapping documents are available with < Hibernate - mapping> Contains 2 < for each class; Class> XML document for the root element of the element.

< Class> The element is used to define a database table specific mapping from a Java class. The Java class name is specified using the name attribute of the class element and the database table name using the table attribute.

< Meta> The element is an optional element that can be used to create a description of the class.

< Id> The element maps the unique ID attribute in the class to the primary key of the database table. The name attribute of the id element refers to the class of the attribute and the column attribute refers to the column in the database table. The type attribute holds the Hibernate mapping type that will be converted from Java to SQL data type.

In the id element < Generator> The element is used to automatically generate primary key values. Set the class attribute of the generated element to native and let Hibernate pick up the identity, sequence, or algorithm in hilo to create the primary key based on the underlying database's supporting capabilities.

< Property> The element is used to map attributes of a Java class to columns in a database table. The name attribute of the element refers to the class of the attribute and the column attribute refers to the column in the database table. The type attribute holds the Hibernate mapping type that will be converted from Java to SQL data type.

< Set> The element sets the relationship between the certificate and the Employee class. We use the cascade attribute < Set> Element to tell Hibernate to save the object of the certificate as an Employee object. The name property is set to the set of variables defined in the parent class, in our case the certificate. For each set of variables, we need to define a separate set of elements in the mapping file.

< Key> The element is the parent object that contains the foreign key, which is the column in the certificate table. Table EMPLOYEE.

< One - to - many> The element represents an Employee object that involves many certificates.

Create an application class:
Finally, we will create the main () method of the application class to run the application. We'll use this application to save some employees along with the record certificate, and then we'll apply the CRUD operation record.


import java.util.*;
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
  private static SessionFactory factory; 
  public static void main(String[] args) {
   try{
     factory = new Configuration().configure().buildSessionFactory();
   }catch (Throwable ex) { 
     System.err.println("Failed to create sessionFactory object." + ex);
     throw new ExceptionInInitializerError(ex); 
   }
   ManageEmployee ME = new ManageEmployee();
   
   HashSet set1 = new HashSet();
   set1.add(new Certificate("MCA"));
   set1.add(new Certificate("MBA"));
   set1.add(new Certificate("PMP"));
   
   
   Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, set1);

   
   HashSet set2 = new HashSet();
   set2.add(new Certificate("BCA"));
   set2.add(new Certificate("BA"));

   
   Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, set2);

   
   ME.listEmployees();

   
   ME.updateEmployee(empID1, 5000);

   
   ME.deleteEmployee(empID2);

   
   ME.listEmployees();

  }

  
  public Integer addEmployee(String fname, String lname, 
                      int salary, Set cert){
   Session session = factory.openSession();
   Transaction tx = null;
   Integer employeeID = null;
   try{
     tx = session.beginTransaction();
     Employee employee = new Employee(fname, lname, salary);
     employee.setCertificates(cert);
     employeeID = (Integer) session.save(employee); 
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
   return employeeID;
  }

  
  public void listEmployees( ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     List employees = session.createQuery("FROM Employee").list(); 
     for (Iterator iterator1 = 
              employees.iterator(); iterator1.hasNext();){
      Employee employee = (Employee) iterator1.next(); 
      System.out.print("First Name: " + employee.getFirstName()); 
      System.out.print(" Last Name: " + employee.getLastName()); 
      System.out.println(" Salary: " + employee.getSalary());
      Set certificates = employee.getCertificates();
      for (Iterator iterator2 = 
             certificates.iterator(); iterator2.hasNext();){
         Certificate certName = (Certificate) iterator2.next(); 
         System.out.println("Certificate: " + certName.getName()); 
      }
     }
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
  }
  
  public void updateEmployee(Integer EmployeeID, int salary ){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     Employee employee = 
          (Employee)session.get(Employee.class, EmployeeID); 
     employee.setSalary( salary );
     session.update(employee);
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
  }
  
  public void deleteEmployee(Integer EmployeeID){
   Session session = factory.openSession();
   Transaction tx = null;
   try{
     tx = session.beginTransaction();
     Employee employee = 
          (Employee)session.get(Employee.class, EmployeeID); 
     session.delete(employee); 
     tx.commit();
   }catch (HibernateException e) {
     if (tx!=null) tx.rollback();
     e.printStackTrace(); 
   }finally {
     session.close(); 
   }
  }
}

Compile and execute:


$java ManageEmployee

.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Manoj Last Name: Kumar Salary: 4000
Certificate: MBA
Certificate: PMP
Certificate: MCA
First Name: Dilip Last Name: Kumar Salary: 3000
Certificate: BCA
Certificate: BA
First Name: Manoj Last Name: Kumar Salary: 5000
Certificate: MBA
Certificate: PMP
Certificate: MCA

If you check the employee and certificate forms, you should record:


mysql> select * from employee;

+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 1 | Manoj   | Kumar   |  5000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)


mysql> select * from certificate;

+----+------------------+-------------+
| id | certificate_name | employee_id |
+----+------------------+-------------+
| 1 | MBA       |     1 |
| 2 | PMP       |     1 |
| 3 | MCA       |     1 |
+----+------------------+-------------+
3 rows in set (0.00 sec)

Related articles: