In a java collection, a map stores elements in key-value pairs. It will not allow duplicate elements. The map interface allows the mapped contents as a set of keys(keys alone) and a collection of values(values alone) or a set of key-value mappings. java.util.HashMap will be useful to initialize an unordered map. In the mapping table, it is denoted with the <map> element. Let us see Hibernate-Map Mapping with one too many mapping formats. Let us take the Teacher class and their corresponding qualifications. i.e. one teacher can have multiple qualifications.
Step by Step Implementation
Create MySQL tables Teacher and Qualification:
-- Teacher create table Teacher ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, PRIMARY KEY (id) ); -- Qualification create table Qualification ( id INT NOT NULL auto_increment, qualification_type VARCHAR(40) default NULL, qualification_name VARCHAR(30) default NULL, teacher_id INT default NULL, PRIMARY KEY (id) ); --One teacher can have multiple qualifications --hence one to many mapping possibility
Let us see a maven-driven eclipse project to show the map mapping functionality.
Project structure:
pom.xml
XML
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 < modelVersion >4.0.0</ modelVersion > < groupId >Hibernate-Map-mapping-Example</ groupId > < artifactId >Hibernate-Map-mapping-Example</ artifactId > < version >0.0.1-SNAPSHOT</ version > < dependencies > < dependency > < groupId >org.hibernate</ groupId > < artifactId >hibernate-core</ artifactId > < version >4.3.0.Final</ version > </ dependency > <!-- As we are connecting with MySQL, this is needed --> < dependency > < groupId >mysql</ groupId > < artifactId >mysql-connector-java</ artifactId > < version >5.1.34</ version > </ dependency > </ dependencies > <!-- Higher java versions are preferred, atleast 1.8 --> < properties > < maven.compiler.source >1.8</ maven.compiler.source > < maven.compiler.target >1.8</ maven.compiler.target > </ properties > </ project > |
First, let us see the bean classes corresponding to the tables namely Teacher and Qualification
Teacher.java
Java
import java.util.Map; public class Teacher { private int id; private String firstName; private String lastName; private int salary; // One teacher can have multiple // qualifications and hence // Map is specified here private Map qualifications; public Teacher() { } public Teacher(String fname, String lname, int salary) { this .firstName = fname; this .lastName = lname; this .salary = salary; } 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 Map getQualifications() { return qualifications; } public void setQualifications(Map qualifications) { this .qualifications = qualifications; } } |
Qualification.java
Java
public class Qualification { private int id; private String name; public Qualification() {} public Qualification(String name) { this .name = name; } public int getId() { return id; } public void setId( int id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } } |
XML files that specify the relationship are as follows
teacher_qualification.hbm.xml
XML
<? xml version = "1.0" encoding = "utf-8" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" < hibernate-mapping > < class name = "com.gfg.hibernate.pojo.Teacher" table = "Teacher" > < meta attribute = "class-description" > This class contains the teacher detail. </ meta > < id name = "id" type = "int" column = "id" > < generator class = "native" /> </ id > <!-- The <map> element is used to set the relationship between Qualification and Teacher classes. We used the cascade attribute in the <map> element to tell Hibernate to persist the Qualification objects at the same time as the Teacher objects. The name attribute is set to the defined Map variable in the parent class, in our case it is qualifications. This is very important to specify for map mapping functionality --> < map name = "qualifications" cascade = "all" > <!-- The <key> element is the column in the Qualification table that holds the foreign key to the parent object ie. table Teacher.--> < key column = "teacher_id" /> <!-- The <index> element is used to represents the key parts of the key/value map pair. The key will be stored in the column qualification_type using a type of string. --> < index column = "qualification_type" type = "string" /> <!-- here the specification of one to many. one teacher can have multiple qualifications --> <!-- <one-to-one>, <many-to-one> or <many-to-many> elements based on the requirement, it is set --> < one-to-many class = "com.gfg.hibernate.pojo.Qualification" /> </ map > <!-- The <property> element is used to map a Java class property to a column in the database table. The name attribute of the element refers to the property in the class and the column attribute refers to the column in the database table. The type attribute holds the hibernate mapping type, this mapping types will convert from Java to SQL data type.--> < 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 = "com.gfg.hibernate.pojo.Qualification" table = "Qualification" > < meta attribute = "class-description" > This class contains the qualification records. </ meta > < id name = "id" type = "int" column = "id" > < generator class = "native" /> </ id > < property name = "name" column = "qualification_name" type = "string" /> </ class > </ hibernate-mapping > |
We need to specify this in the main configuration file
hibernate.cfg.xml
XML
<? xml version = "1.0" encoding = "UTF-8" ?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" < hibernate-configuration > < session-factory > <!-- As we are connecting mysql, those driver classes, database name, username and password are specified Please change the information as per your requirement --> < property name = "connection.driver_class" >com.mysql.jdbc.Driver</ property > < property name = "connection.username" >root</ property > < property name = "connection.password" >admin</ property > <!-- We are going to connect teacher_qualification.hbm.xml which has the table information about teacher and qualification which is present in mysql. One teacher can have multiple qualifications --> < mapping resource = "teacher_qualification.hbm.xml" /> </ session-factory > </ hibernate-configuration > |
Let us do some business functionality like
- Adding Teachers
- Listing Teachers
- Updating the data available for Teachers
- Deleting the data
Configuration of code:
Java
import com.gfg.hibernate.pojo.Qualification; import com.gfg.hibernate.pojo.Teacher; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class TeacherRepository { 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); } } } |
Let us see the code for the addition of teachers
Java
TeacherRepository teacherRepository = new TeacherRepository(); // Let us have a set of qualifications // for the professor HashMap set = new HashMap(); set.put( "Physics" , new Qualification( "BSC" )); set.put( "ComputerScience" , new Qualification( "MSC" )); set.put( "ProjectManagement" , new Qualification( "PMP" )); // Add teacher records in the database Integer teacherId = teacherRepository.addData( "GeekA" , "GeekA" , 40000 , set); // List down all the teacher teacherRepository.listData(); // Method to add a professor details in the database public Integer addData(String fname, String lname, int salary, HashMap qualifications){ Session session = factory.openSession(); Transaction tx = null ; Integer teacherId = null ; try { tx = session.beginTransaction(); Teacher teacher = new Teacher(fname, lname, salary); teacher.setQualifications(qualifications); teacherId = (Integer) session.save(teacher); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return teacherId; } // Method to list all the teachers detail public void listData( ){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); // Need to specify the table name here List teachers = session.createQuery( "FROM Teacher" ).list(); for (Iterator iterator1 = teachers.iterator(); iterator1.hasNext();){ Teacher teacher = (Teacher) iterator1.next(); System.out.print( "First Name: " + teacher.getFirstName()); System.out.print( " Last Name: " + teacher.getLastName()); System.out.println( " Salary: " + teacher.getSalary()); Map teacherMap = teacher.getQualifications(); System.out.println( "Qualification: " + (((Qualification)teacherMap.get( "Physics" )).getName())); System.out.println( "Qualification: " + (((Qualification)teacherMap.get( "ComputerScience" )).getName())); System.out.println( "Qualification: " + (((Qualification)teacherMap.get( "ProjectManagement" )).getName())); } tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } |
On execution of the above code, we can able to see the addition of data in the table.
Output:
In the table, let us check the data
Output:
Let us update the data now
Java
// Update teacher salary records // We need to specify the available teacher // id to have the update to happen teacherRepository.updateData( 1 , 45000 ); // List down all the teacher teacherRepository.listData(); // Method to update salary for a teacher public void updateData(Integer teacherId, int salary ){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); Teacher teacher = (Teacher)session.get(Teacher. class , teacherId); teacher.setSalary( salary ); session.update(teacher); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } |
Let us check the output for the same
Output:
Next, let us see the deletion of data
Java
// Add 1 more record TeacherRepository teacherRepository = new TeacherRepository(); // Let us have a set of qualifications for the professor HashMap set = new HashMap(); set.put( "Physics" , new Qualification( "BSC" )); set.put( "ComputerScience" , new Qualification( "MSC" )); set.put( "ProjectManagement" , new Qualification( "PMP" )); // Add teacher records in the database Integer teacherId = teacherRepository.addData( "GeekB" , "GeekB" , 40000 , set); // List down all the teachers // Here we can able to see 2 teachers teacherRepository.listData(); // delete the specified teacher id // We need to specify the available // teacher id to have the delete to happen teacherRepository.deleteData( 1 ); System.out.println( "After deleting the 1st record.." ); teacherRepository.listData(); // Method to delete salary from the records public void deleteData(Integer teacherId){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); Teacher teacher = (Teacher)session.get(Teacher. class , teacherId); session.delete(teacher); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } |
Output:
The Complete code
Java
import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import com.gfg.hibernate.pojo.Qualification; import com.gfg.hibernate.pojo.Teacher; public class TeacherRepository { 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); } TeacherRepository teacherRepository = new TeacherRepository(); // Let us have a set of qualifications for the professor HashMap set = new HashMap(); set.put( "Physics" , new Qualification( "BSC" )); set.put( "ComputerScience" , new Qualification( "MSC" )); set.put( "ProjectManagement" , new Qualification( "PMP" )); // Add teacher records in the database Integer teacherId = teacherRepository.addData( "GeekA" , "GeekA" , 40000 , set); set = new HashMap(); set.put( "Physics" , new Qualification( "BSC" )); set.put( "ComputerScience" , new Qualification( "MSC" )); set.put( "ProjectManagement" , new Qualification( "PMP" )); teacherId = teacherRepository.addData( "GeekB" , "GeekB" , 40000 , set); // List down all the teachers teacherRepository.listData(); // Update teacher salary records // We need to specify the available teacher // id to have the update to happen teacherRepository.updateData( 1 , 45000 ); // List down all the teacher teacherRepository.listData(); // delete the specified teacher id // We need to specify the available // teacher id to have the delete to happen teacherRepository.deleteData( 1 ); // List down all the teacher System.out.println( "After deleting the 1st record.." ); teacherRepository.listData(); } // Method to add a professor details in the database public Integer addData(String fname, String lname, int salary, HashMap qualifications){ Session session = factory.openSession(); Transaction tx = null ; Integer teacherId = null ; try { tx = session.beginTransaction(); Teacher teacher = new Teacher(fname, lname, salary); teacher.setQualifications(qualifications); teacherId = (Integer) session.save(teacher); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return teacherId; } // Method to list all the teachers detail public void listData( ){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); List teachers = session.createQuery( "FROM Teacher" ).list(); for (Iterator iterator1 = teachers.iterator(); iterator1.hasNext();){ Teacher teacher = (Teacher) iterator1.next(); System.out.print( "First Name: " + teacher.getFirstName()); System.out.print( " Last Name: " + teacher.getLastName()); System.out.println( " Salary: " + teacher.getSalary()); Map teacherMap = teacher.getQualifications(); System.out.println( "Qualification: " + (((Qualification)teacherMap.get( "Physics" )).getName())); System.out.println( "Qualification: " + (((Qualification)teacherMap.get( "ComputerScience" )).getName())); System.out.println( "Qualification: " + (((Qualification)teacherMap.get( "ProjectManagement" )).getName())); } tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } // Method to update salary for a teacher public void updateData(Integer teacherId, int salary ){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); Teacher teacher = (Teacher)session.get(Teacher. class , teacherId); teacher.setSalary( salary ); session.update(teacher); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } // Method to delete salary from the records public void deleteData(Integer teacherId){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); Teacher teacher = (Teacher)session.get(Teacher. class , teacherId); session.delete(teacher); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } } |
Conclusion
As map can able to support key-value pair combinations, we can easily make one to many mapping relationships in Hibernate easily.