Set
A collection Set is a java collection that does not contain any duplicate elements. More formally, Set does not contain any elements on e1 and e2, such that e1.equals(e2), and at most one empty element. So being added to a set of objects must implement equals() and hashCode() methods so that Java can determine whether any two elements/objects are the same.
Sets are mapped to <set> elements in the map table and are initialized in java.util.HashSet. You can use Set collections to have elements in the collection that do not need to be repeated when using the class.
Define RDBMS table:
Consider a case where we need our employee records to be stored in the EMPLOYEE table, with 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, PRIMARY KEY (id));
Furthermore, it is assumed that each employee can have one or more certificates related to him/her. Therefore, we store the relevant information of the certificate in a separate table with the following structure:
create table CERTIFICATE ( id INT NOT NULL auto_increment, certificate_name VARCHAR(30) default NULL, employee_id INT default NULL, PRIMARY KEY (id));
There will be a relationship between a to-many EMPLOYEE and a certificate object:
Define POJO class:
Let's implement our POJO class staff will be used to hold a collection of objects in the EMPLOYEE table and credentialed set variables.
import java.util.*;public class Employee { private int id; private String firstName; private String lastName; private int salary; private Set certificates; public Employee() {} public Employee(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 Set getCertificates() { return certificates; } public void setCertificates( Set certificates ) { this.certificates = certificates; }} Now let's define the certificate of another POJO class corresponding to the table, such a certificate object can store and retrieve the CERTIFICATE table. This class should also implement the equals() and hashCode() methods at the same time, so that Java can determine whether any two elements/objects are the same.
public class Certificate { private int id; private String name; public Certificate() {} public Certificate(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; } public boolean equals(Object obj) { if (obj == null) return false; if (!this.getClass().equals(obj.getClass())) return false; Certificate obj2 = (Certificate)obj; if((this.id == obj2.getId()) && (this.name.equals(obj2.getName()))) { return true; } return false; } public int hashCode() { int tmp = 0; tmp = ( id + name ).hashCode(); return tmp; }} Define Hibernate mapping file:
Let's develop a mapping file that specifies how Hibernate defines a mapping file that maps to a database table. The <SET> element will be used to define the rules used to set the collection.
<?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. Save the file Employee.hbm.xml in the mapping file. Already familiar with most of the mapping details, mapping all elements in the file:
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 the original one to let Hibernate pick it up, either identity, sequence or hilo algorithm 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 is new and has been introduced to set the relationship between the CERTIFICATE and Employee class. We use the <set> element in the cascade attribute to tell Hibernate to save the CERTIFICATE object and the Employee object. The name attribute is set to set the variable in the definition in the parent class, in our case it is 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, and therefore, the certificate object must be related to the parent Employee. You can use any and <one-to-one>, <many-to-one> or <many-to-many> elements as needed.
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 employee records along with the credentials, and then we will apply for records on the CRUD operation.
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:
Here are the steps to compile and run the above application. Make sure that PATH and CLASSPATH are set appropriately before compiling and executing.
The following results will be obtained on the screen and records will be created in the employee and certificate tables.
$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;
+----+------------------+-------------+| id | certificate_name | employee_id |+----+------------------+-------------+| 1 | MBA | 1 || 2 | PMP | 1 || 3 | MCA | 1 |+----+------------------+-------------+3 rows in set (0.00 sec)
mysql>
SortedSet
SortedSet is a java collection that does not contain any duplicate elements and elements that use provide their natural order, or are sorted by a comparator.
A SortedSet map, initialized in the mapping table <set> element and java.util.TreeSet. The sorting attribute can be set to a comparator or natural order. If natural order is used, then its iterator traverses the set elements arranged in ascending order.
We still use the RDBMS table defined in the example above, and there will be a relationship between multiple EMPLOYEE and certificate objects, and the POJO class is also defined above.
Let's implement the POJO class employee will be used to hold a collection of objects in the EMPLOYEE table and a certificated SortedSet variable.
Now let's define the certificate for another POJO class corresponding to the certificate table, such a certificate object can store and retrieve the certificate table. This class should also implement the Comparable interface and the compareTo method will be used to set sort="natural" in the case of mapping files (see map files below), the elements are sorted.
public class Certificate implements Comparable <Certificate>{ private int id; private String name; public Certificate() {} public Certificate(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; } public int compareTo(Certificate that){ final int BEFORE = -1; final int AFTER = 1; if (that == null) { return BEFORE; } Comparable thisCertificate = this.getName(); Comparable thatCertificate = that.getName(); if(thisCertificate == null) { return AFTER; } else if(thatCertificate == null) { return BEFORE; } else { return thisCertificate.compareTo(thatCertificate); } }} Define Hibernate mapping file:
Let's develop a mapping file that specifies how Hibernate defines a mapping file that maps to a database table. The <set> element will be used to define the rules for the SortedSet collection used.
<?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" sort="MyClass"> <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 map file, save the file Employee.hbm.xml in the map file. I've already been familiar with most of the mapping details, but let's see all the elements in the mapping file:
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 the algorithm in either 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.
The <set> element is used to set 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 to the Employee object. The name attribute is set to the variable of the SortedSet defined in the parent class, in our case it is a certificate. The sorting property can be set to natural sorting, or it can be set to custom class implementation as java.util.Comparator. We have used a class MyClass that implements it as java.util.Comparator to reverse the sort order of the certificate class implementation.
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 certificate objects, and therefore, the certificate object must be related to the parent Employee. You can use any and <one-to-one>, <many-to-one> or <many-to-many> elements as needed.
If you use the sort="natural" setting, you do not need to create a separate class, because the certificate class has implemented the Comparable interface and hibernate will use the compareTo (defined as the comparison certificate name in the certificate class). However, we are using a custom comparator class MyClass in our mapping file, so we must create this class based on the sorting algorithm. Use this class to sort in descending order.
import java.util.Comparator;public class MyClass implements Comparator<Certificate>{ public int compare(Certificate o1, Certificate o2) { final int BEFORE = -1; final int AFTER = 1; /* To reverse the sorting order, multiple by -1 */ if (o2 == null) { return BEFORE * -1; } Comparable thisCertificate = o1.getName(); Comparable thatCertificate = o2.getName(); if(thisCertificate == null) { return AFTER * 1; } else if(thatCertificate == null) { return BEFORE * -1; } else { return thisCertificate.compareTo(thatCertificate) * -1; } }} 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 employee records along with the certificate, and then we will apply for records on the CRUD operation.
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 */ TreeSet set1 = new TreeSet(); 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 */ TreeSet set2 = new TreeSet(); 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, SortedSet 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()); SortedSet 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(); } }}After compiling and executing, the following results are obtained on the screen, and records are created in both the employee and certificate tables. You can see that the certificates have been sorted in the opposite order. You can try it by changing the mapping file, just set sort="natural" and execute the program, and compare the results.
$java ManageEmployee
.....VARIOUS LOG MESSAGES WILL DISPLAY HERE.........First Name: Manoj Last Name: Kumar Salary: 4000Certificate: PMPCertificate: MCACertificate: MBAFirst Name: Dilip Last Name: Kumar Salary: 3000Certificate: BCACertificate: BAFirst Name: Manoj Last Name: Kumar Salary: 5000Certificate: PMPCertificate: MCACertificate: MBA
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;
+----+------------------+-------------+| id | certificate_name | employee_id |+----+------------------+-------------+| 1 | MBA | 1 || 2 | PMP | 1 || 3 | MCA | 1 |+----+------------------+-------------+3 rows in set (0.00 sec)