Friday 11 November 2022

Hibernate: handle enum values using @Enumerated annotation

As per 'jakarta.persistence.EnumType', Jakarta support two strategies to handle enum values. Below table summarizes the same.

 

Enum type

Description

ORDINAL

Persist enum according to the enum value’s ordinal position within the enum class, as indicated by java.lang.Enum#ordinal.

STRING

Persist according to the enum value’s name, as indicated by java.lang.Enum#name

  

Example using ORDINAL

@Entity
@Table(name = "person")
public class Person {

	@Id
	private Integer id;

	private String name;

	@Enumerated(EnumType.ORDINAL)
	private Gender gender;

	.........
	.........
}

In the ORDINAL example, the gender column is defined as a (nullable) INTEGER type and would hold:

 

a.   NULL: For null values

b.   0: For the MALE enum

c.    1: For the FEMALE enum

 

 

Example using STRING

@Entity
@Table(name = "person")
public class Person {

	@Id
	private Integer id;

	private String name;

	@Enumerated(EnumType.STRING)
	private Gender gender;

	..........
	..........
}

In the STRING example, the gender column is defined as a (nullable) VARCHAR type and would hold:

 

a.   NULL: For null values

b.   MALE: For the MALE enum

c.    FEMALE: For the FEMALE enum

 

Follow below step-by-step procedure to build complete working application.

 

Step 1: Create new maven project ‘hibernate-enumerated-ordinal-demo’.

 

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.0</modelVersion>
	<groupId>com.sample.app</groupId>
	<artifactId>hibernate-enumerated-ordinal-demo</artifactId>
	<version>1</version>

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

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

	</properties>

	<dependencies>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>42.4.1</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>6.1.2.Final</version>
		</dependency>

		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>javax.persistence-api</artifactId>
			<version>2.2</version>
		</dependency>


	</dependencies>
</project>

Step 3: Define Gender enum.

Gender.java

package com.sample.app.enums;

public enum Gender {
	MALE,
	FEMALE
}

Step 4: Define Person entity class.

 

Person.java

package com.sample.app.entity;

import com.sample.app.enums.Gender;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "person")
public class Person {

	@Id
	private Integer id;

	private String name;

	@Enumerated(EnumType.ORDINAL)
	private Gender gender;

	public Person(Integer id, String name, Gender gender) {
		this.id = id;
		this.name = name;
		this.gender = gender;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public Gender getGender() {
		return gender;
	}

	public void setGender(Gender gender) {
		this.gender = gender;
	}

}

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

 

hibernate.cfg.xml

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

	<session-factory>

		<!-- Database Connection settings -->
		<property name="connection.driver_class">org.postgresql.Driver</property>
		<property name="connection.url">jdbc:postgresql://127.0.0.1:5432/test</property>
		<property name="connection.username">postgres</property>
		<property name="connection.password">postgres</property>

		<!-- Enable the logging of all the generated SQL statements to the console -->
		<property name="show_sql">true</property>

		<!-- Format the generated SQL statement to make it more readable, -->
		<property name="format_sql">true</property>

		<!-- Hibernate will put comments inside all generated SQL statements to 
			hint what’s the generated SQL trying to do -->
		<property name="use_sql_comments">false</property>

		<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>

		<property name="hbm2ddl.auto">update</property>

		<!-- mappings for annotated classes -->
		<mapping class="com.sample.app.entity.Person" />

	</session-factory>

</hibernate-configuration>

Step 6: Define main application class.

 

App.java

package com.sample.app;

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.entity.Person;
import com.sample.app.enums.Gender;

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

	private static SessionFactory buildSessionFactory() {
		try {

			final StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
					.configure("hibernate.cfg.xml").build();

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

			return metaData.getSessionFactoryBuilder().build();

		} catch (Throwable ex) {
			throw new ExceptionInInitializerError(ex);
		}

	}

	public static void main(final String args[]) {

		Person p1 = new Person(1, "Srinu", Gender.MALE);
		Person p2 = new Person(2, "Swetha", Gender.FEMALE);

		try (final Session session = SESSION_FACTORY.openSession()) {
			session.beginTransaction();

			session.persist(p1);
			session.persist(p2);

			session.getTransaction().commit();

		}

	}
}

Total project structure looks like below.




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

Aug 12, 2022 11:22:38 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:postgresql://127.0.0.1:5432/test]
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=postgres}
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 20 (min=1)
Aug 12, 2022 11:22:38 AM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Aug 12, 2022 11:22:39 AM org.hibernate.metamodel.internal.EntityInstantiatorPojoStandard resolveConstructor
INFO: HHH000182: No default (no-argument) constructor for class: com.sample.app.entity.Person (class must be instantiated by Interceptor)
Aug 12, 2022 11:22:39 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@3ae126d1] 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 person (
       id integer not null,
        gender smallint,
        name varchar(255),
        primary key (id)
    )
Aug 12, 2022 11:22:39 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
        person
        (gender, name, id) 
    values
        (?, ?, ?)
Hibernate: 
    insert 
    into
        person
        (gender, name, id) 
    values
        (?, ?, ?)

Query the table person to confirm the entries.

test=# SELECT * FROM person;
 id | gender |  name  
----+--------+--------
  1 |      0 | Srinu
  2 |      1 | Swetha
(2 rows)

You can download complete working application from this link.


Previous                                                    Next                                                    Home

No comments:

Post a Comment