Hibernate - SortedSet Mapping
SortedSet can be viewed in a group of elements and they do not have a duplicate element and ascending order is maintained in its elements. By using <set> elements we can use them and the entity should have a Sortedset of values. As an example, we can have a freelancer who works for multiple companies on a shift basis. Here also the one-to-many relationship is seen as a freelancer can belong to multiple (many) companies.
Example Project
Project Structure:

This is a maven project. Let us see pom.xml
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>HibernateSortedSetMapping</groupId>
<artifactId>HibernateSortedSetMapping</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 us start with POJO classes
Freelancer.java
import java.util.SortedSet;
public class Freelancer {
// data members
private int freelancerId;
private String freelancerName;
private int freelancerAge;
private int pricePerHour;
// As one freelancer works for multiple companies, let
// us have that as SortedSet here for companies
private SortedSet companies;
public int getFreelancerId() { return freelancerId; }
public void setFreelancerId(int freelancerId)
{
this.freelancerId = freelancerId;
}
public String getFreelancerName()
{
return freelancerName;
}
public void setFreelancerName(String freelancerName)
{
this.freelancerName = freelancerName;
}
public int getFreelancerAge() { return freelancerAge; }
public void setFreelancerAge(int freelancerAge)
{
this.freelancerAge = freelancerAge;
}
public int getPricePerHour() { return pricePerHour; }
public void setPricePerHour(int pricePerHour)
{
this.pricePerHour = pricePerHour;
}
public SortedSet getCompanies() { return companies; }
public void setCompanies(SortedSet companies)
{
this.companies = companies;
}
// no argument constructor
public Freelancer() {}
// argument constructor
public Freelancer(String freelancerName,
int freelancerAge, int pricePerHour)
{
this.freelancerName = freelancerName;
this.freelancerAge = freelancerAge;
this.pricePerHour = pricePerHour;
}
}
Company.java
public class Company implements Comparable<Company> {
private int companyId;
private String companyName;
public int getCompanyId() { return companyId; }
public void setCompanyId(int companyId)
{
this.companyId = companyId;
}
public String getCompanyName() { return companyName; }
public void setCompanyName(String companyName)
{
this.companyName = companyName;
}
public Company(String companyName)
{
this.companyName = companyName;
}
public Company() {}
@Override
// This method has to be implemented as we are following
// SortedSet
public int compareTo(Company company)
{
if (company == null) {
return -1;
}
Comparable company1 = this.getCompanyName();
Comparable company2 = company.getCompanyName();
if (company1 == null) {
return 1;
}
else if (company2 == null) {
return -1;
}
else {
return company1.compareTo(company2);
}
}
}
Let us see the configuration files
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<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 -->
<!-- This property creates table in MySQL automatically
according to the specifications
given in mapping resource file which in turn maps to the POJO class -->
<property name="hbm2ddl.auto">update</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/geeksforgeeks?serverTimezone=UTC</property>
<property name="connection.username">root</property>
<property name="connection.password">admin</property>
<!-- Helps to show the correct sql for each
and every hibernate operation -->
<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="freelancer.hbm.xml"/>
<mapping resource="company.hbm.xml"/>
</session-factory>
</hibernate-configuration>
freelancer.hbm.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- In MySQL, 'freelancer' table is created if it is not there and it
should have 4 attributes namely freelancerId, freelancerName,
freelancerAge and pricePerHour -->
<class name="com.gfg.sortedsetmapping.pojo.Freelancer" table="freelancer">
<id name="freelancerId" type="int" column="freelancerId">
<generator class="native"></generator>
</id>
<property name="freelancerName" column="freelancerName" type="string"/>
<property name="freelancerAge" column="freelancerAge" type="int"/>
<property name="pricePerHour" column="pricePerHour" type="int"/>
<!-- We are following SortedSet Pattern. Hence should provide 'set' and also 'sort' nature
Here one to many relationship is followed and it denote a key column as well -->
<set name="companies" cascade="all" sort="natural">
<key column="freelancerId"/>
<one-to-many class="com.gfg.sortedsetmapping.pojo.Company"/>
</set>
</class>
</hibernate-mapping>
company.hbm.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- In MySQL, 'company' table is created if it is not there and it
should have 2 attributes namely companyId and companyName -->
<hibernate-mapping>
<class name="com.gfg.sortedsetmapping.pojo.Company" table="company">
<id name="companyId" type="int" column="companyId">
<generator class="native"></generator>
</id>
<property name="companyName" column="companyName" type="string"></property>
</class>
</hibernate-mapping>
SortedSetMappingPatternOfStoringData.java
import com.gfg.sortedsetmapping.pojo.Company;
import com.gfg.sortedsetmapping.pojo.Freelancer;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class SortedSetMappingPatternOfStoringData {
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);
}
// As one freelancer works for multiple companies,
// via TreeSet we can represent that
TreeSet companySet1 = new TreeSet();
companySet1.add(new Company("Company A"));
companySet1.add(new Company("Company B"));
TreeSet companySet2 = new TreeSet();
companySet2.add(new Company("Company A"));
companySet2.add(new Company("Company C"));
companySet2.add(new Company("Company E"));
// Create the Freelancer object.
Freelancer freelancer1
= new Freelancer("Freelancer A", 20, 1000);
freelancer1.setCompanies(
companySet1); // Freelancer A associated to 2
// companies
Freelancer freelancer2
= new Freelancer("Freelancer B", 20, 2000);
freelancer2.setCompanies(
companySet2); // Freelancer B associated to 2
// companies
SortedSetMappingPatternOfStoringData
sortedMapMappingPatternOfStoringData
= new SortedSetMappingPatternOfStoringData();
// insert freelancer object.
Integer freelancerId1
= sortedMapMappingPatternOfStoringData
.addFreelancer(freelancer1);
Integer freelancerId2
= sortedMapMappingPatternOfStoringData
.addFreelancer(freelancer2);
// show all Language and book details object.
sortedMapMappingPatternOfStoringData
.listFreelancerAndCompanyDetails();
}
public Integer addFreelancer(Freelancer freelancer)
{
Session session = factory.openSession();
Transaction tx = null;
Integer languageId = null;
try {
tx = session.beginTransaction();
languageId = (Integer)session.save(freelancer);
tx.commit();
}
catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
}
finally {
session.close();
}
return languageId;
}
// Method to list all the freelancers and company detail
public void listFreelancerAndCompanyDetails()
{
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List<Freelancer> freelancers
= session.createQuery("FROM Freelancer")
.list();
for (Freelancer freelancer : freelancers) {
System.out.println(
"Freelancer Name: "
+ freelancer.getFreelancerName());
System.out.println(
"Freelancer Age: "
+ freelancer.getFreelancerAge());
System.out.println(
"Price Per Hour: "
+ freelancer.getPricePerHour());
Set<Company> companies
= freelancer.getCompanies();
for (Company company : companies) {
System.out.println(
"Company Name:"
+ company.getCompanyName());
}
}
tx.commit();
}
catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
}
finally {
session.close();
}
}
}
On execution of the project.
Output:

Conclusion
The one-to-many relationship can be easily depicted via SortedSet and from the output, it is proved that no duplicate elements and ascending order is maintained in the output.