Many-to-One mapping
Many-to-one associations are the most common association relationships, where an object can be associated with multiple objects. For example, one identical address object may be associated with objects of multiple employees.
Define RDBMS table:
Consider a situation where we need 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));
Furthermore, many employees can have the same address, so this association can be presented using many one-to-one associations. We store the information related to the address 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));
Create RBDMS tables at the same time and let them prepare for the next implementation.
Define POJO class:
Let's implement a POJO class employee that will be used to hold variables of the object and its address type with the EMPLOYEE table.
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 instructs Hibernate how to define classes map to database tables. <many-to-one>Processing elements will be used to define rules to establish a many-to-one relationship between 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/> </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" 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/> </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>
The format <classname>.hbm.xml in the mapping file that should be saved. Save the file Employee.hbm.xml in the mapping file. Already familiar with most of the mapping details, but let's look at all the elements in the mapping file again:
A mapped document is an XML document with <hibernate-mapping> as a root element corresponding to each class containing 2 <class> elements.
The <class> element is used to define a database table specific mapping from a Java class. Java class name specifies the name attribute of the class element and the table attribute database table name specifies.
The <meta> element is an optional element that can be used to create a description of the class.
The <id> 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 columns in the database table. The type attribute saves the Hibernate mapping type, which will be converted from Java to SQL data type.
The primary key value in the <generator> element within the id element is used to automatically generate. Set the class attribute of the generated element to natively let Hibernate pick up the algorithms of whether it is identity, sequence or hilo to create primary keys according to the support capabilities of the underlying database.
The <property> element is used to map properties of a Java class to columns in a database table. The name attribute of an element refers to the class of the attribute and the column attribute refers to the columns in the database table. The type attribute saves the Hibernate mapping type, which will be converted from Java to SQL data type.
<many-to-one>Processing element is used to set the relationship between EMPLOYEE and the entity that address. The name attribute is set to a variable defined in the parent class, in our case it is the address. The column attribute is used for column names in the parent table EMPLOYEE set.
Finally, we will create the main() method of the application class to run the application. We will use this application to save some employees along with their address to record their address, and then we will apply for the CRUD operation on the 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(); /* Let us have one address object */ Address address = ME.addAddress("Kondapur","Hyderabad","AP","532"); /* Add employee records in the database */ Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, address); /* Add another employee record in the database */ Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, address); /* List down all the employees */ ME.listEmployee(); /* Update employee's salary records */ ME.updateEmployee(empID1, 5000); /* Delete an employee from the database */ ME.deleteEmployee(empID2); /* List down all the employees */ ME.listEmployees(); } /* Method to add an address record in the database */ public Address addressAddress(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; } /* Method to add an employee record in the database */ 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 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; } /* Method to list all the employees details */ 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(); } } /* Method to update salary for an employee */ public void updateEmployee(Integer EmployeeID, int salary ){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Employee 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(); } } /* Method to delete an employee from the records */ public void deleteEmployee(Integer EmployeeID){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Employee 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. Make sure that PATH and CLASSPATH are set appropriately before compiling and executing.
Get the following results on the screen and records are created in both the employee and address tables.
$java ManageEmployee
.....VARIOUS LOG MESSAGES WILL DISPLAY HERE.........First Name: Manoj Last Name: Kumar Salary: 4000Address Street: Kondapur City: Hyderabad State: AP Zipcode: 532First Name: Dilip Last Name: Kumar Salary: 3000Address Street: Kondapur City: Hyderabad State: AP Zipcode: 532First Name: Manoj Last Name: Kumar Salary: 5000Address Street: Kondapur City: Hyderabad State: AP Zipcode: 532
If you check the employee and address table, you should record it:
mysql> select * from EMPLOYEE;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
mysql> select * from ADDRESS;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
One-to-Many Mapping
A one-to-many mapping can be implemented using a set of Java collections that do not contain any duplicate elements. We've seen how to set maps in Hibernate, so if you've learned about set mappings, then all settings can be used for one-to-many mappings.
The set is mapped to the <set> element in the map table and is initialized in java.util.HashSet. You can use Set collections in a class, with an element in the collection that does not require duplication.
We still use the RDBMS table and POJO classes defined in the above example.
Define Hibernate mapping file:
Let's instruct Hibernate how to define a class mapped to a database table's mapping file.
<?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/> </id> <set name="certificates" cascade="all"> <key column="employee_id"/> <one-to-many/> </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/> </id> <property name="name" column="certificate_name" type="string"/> </class></hibernate-mapping>
The format <classname>.hbm.xml in the mapping file that should be saved. 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 at all the elements in the mapping file again:
A mapped document is an XML document with <hibernate-mapping> as a root element corresponding to each class containing 2 <class> elements.
The <class> element is used to define a database table specific mapping from a Java class. Java class name specifies the name attribute of the class element and the table attribute database table name specifies.
The <meta> element is an optional element that can be used to create a description of the class.
The <id> 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 columns in the database table. The type attribute saves the Hibernate mapping type, which will be converted from Java to SQL data type.
The <generator> element within the id element is used to automatically generate the primary key value. Set the class attribute of the generated element to natively let Hibernate pick up identity, sequence or hilo algorithms to create primary keys according to the support capabilities of the underlying database.
The <property> element is used to map properties of a Java class to columns in a database table. The name attribute of an element refers to the class of the attribute and the column attribute refers to the columns in the database table. The type attribute saves the Hibernate mapping type, which will be converted from Java to SQL data type.
The <set> element sets the relationship between the certificate and the Employee class. We use the <set> element in the cascade attribute to tell Hibernate to save the certificate object and also be the Employee object. The name attribute is set to the set of variables defined in the parent class, in our example is the certificate. For each set of variables, we need to define a separate set of elements in the mapping file.
The <key> element is the parent object containing a foreign key, that is, the column in the certificate table. Table EMPLOYEE.
The <one-to-many> element indicates that an Employee object involves many certificates.
Create an application class:
Finally, we will create the main() method of the application class to run the application. We will use this app to save some employees along with the record certificate, and then we will apply the CRUD operation record on.
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(); /* Let us have a set of certificates for the first employee */ HashSet set1 = new HashSet(); set1.add(new Certificate("MCA")); set1.add(new Certificate("MBA")); set1.add(new Certificate("MBA")); set1.add(new Certificate("PMP")); /* Add employee records in the database */ Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, set1); /* Another set of certificates for the second employee */ HashSet set2 = new HashSet(); set2.add(new Certificate("BCA")); set2.add(new Certificate("BA")); /* Add another employee record in the database */ Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, set2); /* List down all the employees */ ME.listEmployee(); /* Update employee's salary records */ ME.updateEmployee(empID1, 5000); /* Delete an employee from the database */ ME.deleteEmployee(empID2); /* List down all the employees */ ME.listEmployee(); } /* Method to add an employee record in the database */ 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 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; } /* Method to list all the employees details */ 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(); } } /* Method to update salary for an employee */ public void updateEmployee(Integer EmployeeID, int salary ){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Employee 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(); } } /* Method to delete an employee from the records */ public void deleteEmployee(Integer EmployeeID){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Employee 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: 4000Certificate: MBACertificate: PMPCertificate: MCAFirst Name: Dilip Last Name: Kumar Salary: 3000Certificate: BCACertificate: BAFirst Name: Manoj Last Name: Kumar Salary: 5000Certificate: MBACertificate: PMPCertificate: MCA
If you check the employee and certificate form, you should record it:
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;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------