Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Hibernate 6: Map a set using @ElementCollection

Sometimes, you may want to deal with the embeddable data associated with an entity.

 

For example,

a.   An employee might have one or more communication addresses

b.   A person might have some alias/nick names.

 

In both the cases, the collection of addresses or collection of nick names do not make any sense outside of employee object. In this case, we can model, these nick names as embeddable collections inside an entity and no need to model these nick names as another entity.

 

Example

@ElementCollection
private Set nickNames;

You can even specify the sort order of set elements in two ways.

 

Approach 1: By implementing Comparable interface.

@Embeddable
public class NickName implements ComparableNickName> {

}

@Entity
@Table(name = "employee")
public class Employee {

@ElementCollection
@SortNatural
private SortedSet nickNames;

}

Since NickName is defined as Comparable, its # compareTo method will be used to sort the elements in this set.

 

Approach 2: Using custom comparator.

@ElementCollection
@SortComparator( NickNameComparator.class )
private SortedSet names;

In approach 2, the explicit NickNameComparator will be used instead to sort the data.

 

Find the below working application.

 

Step 1: Create new maven project ‘hibernate-map-set’.

 

Step 2: Update pom.xml with maven dependencies.

 

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.0modelVersion>
groupId>com.sample.appgroupId>
artifactId>hibernate-map-setartifactId>
version>1version>

properties>
project.build.sourceEncoding>UTF-8project.build.sourceEncoding>

java.version>15java.version>
maven.compiler.source>${java.version}maven.compiler.source>
maven.compiler.target>${java.version}maven.compiler.target>

properties>

dependencies>
dependency>
groupId>org.postgresqlgroupId>
artifactId>postgresqlartifactId>
version>42.4.1version>
dependency>

dependency>
groupId>org.hibernategroupId>
artifactId>hibernate-coreartifactId>
version>6.1.2.Finalversion>
dependency>


dependencies>
project>

Step 3: Define NickName class.

 

NickName.java

package com.sample.app.dto;

import jakarta.persistence.Embeddable;

@Embeddable
public class NickName implements ComparableNickName> {

private String name;

public NickName() {
}

public NickName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "NickName [name=" + name + "]";
}

@Override
public int compareTo(NickName nickName) {
if (nickName == null || nickName.name == null)
return 0;

return nickName.name.compareTo(this.name);
}

}

Step 4: Define Employee entity class.

 

Employee.java

package com.sample.app.entity;

import java.util.SortedSet;

import org.hibernate.annotations.SortNatural;

import com.sample.app.dto.NickName;

import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "employee")
public class Employee {
@Id
@Column(name = "employee_id")
private int id;

private String name;

@ElementCollection
@SortNatural
private SortedSet nickNames;

public Employee() {
}

public Employee(int id, String name, SortedSet nickNames) {
this.id = id;
this.name = name;
this.nickNames = nickNames;
}

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 SortedSetgetNickNames() {
return nickNames;
}

public void setNickNames(SortedSet nickNames) {
this.nickNames = nickNames;
}

@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", nickNames=" + nickNames + "]";
}

}

 

Step 5: Create hibernate.cfg.xml file under src/main/resources folder.

 

hibernate.cfg.xml

 

xml version='1.0' encoding='utf-8'?>
br> "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

hibernate-configuration>

session-factory>


property name="connection.driver_class">org.postgresql.Driverproperty>
property name="connection.url">jdbc:postgresql://127.0.0.1:5432/testproperty>
property name="connection.username">postgresproperty>
property name="connection.password">postgresproperty>


property name="show_sql">trueproperty>


property name="format_sql">trueproperty>


property name="use_sql_comments">falseproperty>


property name="dialect">org.hibernate.dialect.PostgreSQLDialectproperty>


property name="hbm2ddl.auto">createproperty>


mapping class="com.sample.app.entity.Employee" />

session-factory>

hibernate-configuration>

 

Step 6: Define main application class.

 

App.java

 

package com.sample.app;

import java.util.*;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import com.sample.app.dto.NickName;
import com.sample.app.entity.Employee;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;

public class App {
private static SessionFactory sessionFactory = buildSessionFactory();

private static ListloadAllData(Class clazz, Session session) {
final CriteriaBuilder builder = session.getCriteriaBuilder();
final CriteriaQuery criteria = builder.createQuery(clazz);
criteria.from(clazz);
return session.createQuery(criteria).getResultList();
}

private static SessionFactory buildSessionFactory() {
try {
if (sessionFactory == null) {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure("hibernate.cfg.xml").build();

Metadata metaData = new MetadataSources(standardRegistry).getMetadataBuilder().build();

sessionFactory = metaData.getSessionFactoryBuilder().build();
}
return sessionFactory;
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}

public static void main(String args[]) {

try (Session session = sessionFactory.openSession()) {

session.beginTransaction();

TreeSet nickNamesSet = new TreeSet();
nickNamesSet.add(new NickName("Vasu dev"));
nickNamesSet.add(new NickName("Rishikesha"));
nickNamesSet.add(new NickName("Keshava"));
nickNamesSet.add(new NickName("Sri Krishna"));
nickNamesSet.add(new NickName("Nandakumara"));

Employee emp = new Employee(1, "Krishna", nickNamesSet);
session.persist(emp);
session.flush();
session.getTransaction().commit();

List employees = loadAllData(Employee.class, session);
for (Employee emp1 : employees) {
System.out.println(emp1);
}

}

}
}

 Total project structure looks like below.

 

Run App.java, you will see below messages in the console.

Sep 13, 2022 11:36:56 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:postgresql://127.0.0.1:5432/test]
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=postgres}
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections
INFO: HHH10001115: Connection pool size: 20 (min=1)
Sep 13, 2022 11:36:57 AM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Hibernate:

alter table if exists Employee_nickNames
drop constraint if exists FK5ahwp3hworqds1shqyvktsyg7
Sep 13, 2022 11:36:57 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$
ConnectionProviderJdbcConnectionAccess@f1dd5b4] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate:

drop table if exists employee cascade
Hibernate:

drop table if exists Employee_nickNames cascade
Hibernate:

create table employee (
employee_id integer not null,
name varchar(255),
primary key (employee_id)
)
Sep 13, 2022 11:36:57 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@48eb001a] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate:

create table Employee_nickNames (
Employee_employee_id integer not null,
name varchar(255)
)
Hibernate:

alter table if exists Employee_nickNames
add constraint FK5ahwp3hworqds1shqyvktsyg7
foreign key (Employee_employee_id)
references employee
Sep 13, 2022 11:36:57 AM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate:
insert
into
employee
(name, employee_id)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
delete
from
Employee_nickNames
where
Employee_employee_id=?
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
insert
into
Employee_nickNames
(Employee_employee_id, name)
values
(?, ?)
Hibernate:
select
e1_0.employee_id,
e1_0.name
from
employee e1_0
Employee [id=1, name=Krishna, nickNames=[NickName [name=Vasu dev], NickName [name=Sri Krishna], NickName [name=Rishikesha], NickName [name=Nandakumara], NickName [name=Keshava]]]

 

From the output, you can confirm that the Nick names are sorted by their name in descendin order.

 

Query database to confirm DDL.



This post first appeared on Java Tutorial : Blog To Learn Java Programming, please read the originial post: here

Share the post

Hibernate 6: Map a set using @ElementCollection

×

Subscribe to Java Tutorial : Blog To Learn Java Programming

Get updates delivered right to your inbox!

Thank you for your subscription

×