SortedMap is a map that always maintains its corresponding entries in ascending key order. In Hibernate, using the <map> element and ‘sort’ as ‘natural’ we can maintain the SortedMap. Let us see that by using the one-to-many relationship concept. For example, for a programming language like Java, many books are written. If SortedMap is followed, the books are organized in alphabetical order. Let us see that via a sample project.
Example Project
Project Structure:
Let us create MySQL tables.
-- Main table which has languagename like Java CREATE TABLE `programmingLanguages` ( `id` int(11) NOT NULL AUTO_INCREMENT, `languageName` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ); -- Child table that has book details related to a languageId and hence it is referred here -- Via sortedmapping in hibernate, master detail relationship is getting set CREATE TABLE `bookDetails` ( `id` int(11) NOT NULL AUTO_INCREMENT, `bookName` varchar(40) DEFAULT NULL, `authorName` varchar(30) DEFAULT NULL, `languageId` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ;
Maven-driven project. Let’s see the pom.xml file.
pom.xml
XML
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 < modelVersion >4.0.0</ modelVersion > < groupId >HibernateSortedMapMapping</ groupId > < artifactId >HibernateSortedMapMapping</ artifactId > < version >0.0.1-SNAPSHOT</ version > < build > < sourceDirectory >src</ sourceDirectory > < resources > < resource > < directory >src</ directory > < excludes > < exclude >**/*.java</ exclude > </ excludes > </ resource > </ resources > < plugins > < plugin > < artifactId >maven-compiler-plugin</ artifactId > < version >3.8.1</ version > < configuration > < release >9</ release > </ configuration > </ plugin > </ plugins > </ build > < dependencies > < dependency > < groupId >org.hibernate</ groupId > < artifactId >hibernate-core</ artifactId > < version >5.4.15.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 > < properties > < maven.compiler.source >1.8</ maven.compiler.source > < maven.compiler.target >1.8</ maven.compiler.target > </ properties > </ project > |
Let’s start with POJO classes. As two tables are there, let’s have 2 POJO classes each for one table.
ProgrammingLanguages.java
Java
import java.util.SortedMap; public class ProgrammingLanguages { // data members private int id; // As we are seeing SortedMap example, let us have the // books to be of java.util.SortedMap public SortedMap getBooks() { return books; } public void setBooks(SortedMap books) { this .books = books; } private String languageName; private SortedMap books; public int getId() { return id; } public void setId( int id) { this .id = id; } public String getLanguageName() { return languageName; } public void setLanguageName(String languageName) { this .languageName = languageName; } // no argument constructor public ProgrammingLanguages() {} // argument constructor public ProgrammingLanguages(String languageName) { this .languageName = languageName; } } |
Book.java
Java
public class Book implements Comparable<String> { private int id; private String bookName; public int getId() { return id; } public void setId( int id) { this .id = id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this .bookName = bookName; } public String getAuthorName() { return authorName; } public void setAuthorName(String authorName) { this .authorName = authorName; } private String authorName; // argument Constructor public Book(String bookName, String authorName) { this .bookName = bookName; this .authorName = authorName; } // No argument Constructor public Book() {} // This method has to be implemented as we are using // Comparable Sorting is getting followed for SortedMap @Override public int compareTo(String book) { if ( this == null ) { return 1 ; } else if (book == null ) { return - 1 ; } else { return this .compareTo(book); } } } |
Let us see the configuration files now
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 = "hbm2ddl.auto" >update</ property > < property name = "connection.driver_class" >com.mysql.jdbc.Driver</ property > < property name = "connection.username" >root</ property > < property name = "connection.password" >admin</ property > <!-- This will be helpful to know how the data is getting queried in backend --> < property name = "show_sql" >true</ property > <!-- We are going to connect language.hbm.xml and book.hbm.xml which has the table information about programmingLanguages and book which is present in mysql --> < mapping resource = "language.hbm.xml" /> < mapping resource = "book.hbm.xml" /> </ session-factory > </ hibernate-configuration > |
In the main configuration file, 2 mapping resources are added. Let us see them
language.hbm.xml
XML
<? xml version = '1.0' encoding = 'UTF-8' ?> <!DOCTYPE hibernate-mapping SYSTEM < hibernate-mapping > <!-- Always keep the POJO class name and MySQL table name alike --> < class name = "com.gfg.sortedmapmapping.pojo.ProgrammingLanguages" table = "programminglanguages" > < id name = "id" type = "int" column = "id" > < generator class = "native" ></ generator > </ id > < property name = "languageName" column = "languageName" type = "string" /> <!-- For using SortedMap, we have to follow the below syntax key column is the connecting column between both the labels index column is required for SortedMap and that is not required in the case of bag mapping Relationship followed here is one-to-many as one language can have multiple books --> < map name = "books" cascade = "all" sort = "natural" > < key column = "languageId" /> < index column = "Language_Class" type = "string" /> < one-to-many class = "com.gfg.sortedmapmapping.pojo.Book" /> </ map > </ class > </ hibernate-mapping > |
book.hbm.xml
XML
<? xml version = '1.0' encoding = 'UTF-8' ?> <!DOCTYPE hibernate-mapping SYSTEM < hibernate-mapping > < class name = "com.gfg.sortedmapmapping.pojo.Book" table = "bookdetails" > < id name = "id" type = "int" column = "id" > < generator class = "native" ></ generator > </ id > < property name = "bookName" column = "bookName" type = "string" ></ property > < property name = "authorName" column = "authorName" type = "string" ></ property > </ class > </ hibernate-mapping > |
Let us go for the main class which does the addition of programming language and books into the MySQL table and listing from there
SortedMapMappingPatternOfStoringData.java
Java
import com.gfg.sortedmapmapping.pojo.Book; import com.gfg.sortedmapmapping.pojo.ProgrammingLanguages; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.security.auth.Subject; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class SortedMapMappingPatternOfStoringData { 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 add Java as programming language and for // that effectively 3 books (with author name) // details are added TreeMap map = new TreeMap(); map.put( "Java1" , new Book( "J2EE" , "Dave Evans" )); map.put( "Java2" , new Book( "Core Java Volume I" , "Cay S. Horstmann" )); map.put( "Java3" , new Book( "Effective Java" , "Joshua Bloch" )); // Create the Language object. ProgrammingLanguages language = new ProgrammingLanguages( "Java" ); language.setBooks(map); SortedMapMappingPatternOfStoringData sortedMapMappingPatternOfStoringData = new SortedMapMappingPatternOfStoringData(); // insert language object. Integer languageId = sortedMapMappingPatternOfStoringData .addLanguage(language); // show all Language and book details object. sortedMapMappingPatternOfStoringData .listLanguageAndBookDetails(); } /* Method to add programming languages in the database */ public Integer addLanguage(ProgrammingLanguages language) { Session session = factory.openSession(); Transaction tx = null ; Integer languageId = null ; try { tx = session.beginTransaction(); languageId = (Integer)session.save(language); tx.commit(); } catch (HibernateException e) { if (tx != null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return languageId; } /* Method to list all the language and book detail */ public void listLanguageAndBookDetails() { Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); List programmingLanguages = session .createQuery( "FROM ProgrammingLanguages" ) .list(); for (Iterator iterator = programmingLanguages.iterator(); iterator.hasNext();) { ProgrammingLanguages language = (ProgrammingLanguages)iterator.next(); System.out.print( "Language Name: " + language.getLanguageName()); Map books = language.getBooks(); System.out.println( "Book Name:" + ((Book)books.get( "Java1" )) .getBookName()); System.out.println( "Author Name:" + ((Book)books.get( "Java1" )) .getAuthorName()); System.out.println( "Book Name:" + ((Book)books.get( "Java2" )) .getBookName()); System.out.println( "Author Name:" + ((Book)books.get( "Java2" )) .getAuthorName()); System.out.println( "Book Name:" + ((Book)books.get( "Java3" )) .getBookName()); System.out.println( "Author Name:" + ((Book)books.get( "Java3" )) .getAuthorName()); } tx.commit(); } catch (HibernateException e) { if (tx != null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } } |
On running the project, we can see the below output in the console.
Output:
Let us see the output explanation in detail
MySQL table output:
Conclusion
In sorted mapping, the index column is a must and it is represented in the MySql output as well. While storing as well, according to the alphabetical order of book name, they are stored in MySQL