We can map an enum to a database column type by implementing AttributeConverter interface.
Step 1: Define Gender enum class.
Gender.java
public enum Gender {
MALE('M'), FEMALE('F');
private final char code;
Gender(char code) {
this.code = code;
}
public static Gender fromCode(char genderCode) {
if (genderCode == 'F' || genderCode == 'f') {
return FEMALE;
}
if (genderCode == 'M' || genderCode == 'm') {
return MALE;
}
throw new UnsupportedOperationException("The code " + genderCode + " is not supported!");
}
public char getCode() {
return code;
}
}
Step 2: Implement AttributeConverter interface and override convertToDatabaseColumn, convertToEntityAttribute methods.
@Converter
public class GenderConverter implements AttributeConverter<Gender, Character> {
@Override
public Character convertToDatabaseColumn(Gender gender) {
if (gender == null) {
return null;
}
return gender.getCode();
}
@Override
public Gender convertToEntityAttribute(Character genderCode) {
if (genderCode == null) {
return null;
}
return Gender.fromCode(genderCode);
}
}
Step 3: Use the converter defined in step 2 while defining enum variables in the entity class.
@Entity
@Table(name = "person")
public class Person {
@Id
private Integer id;
private String name;
@Convert(converter = GenderConverter.class)
private Gender gender;
......
......
}
Find the below working application.
Step 1: Create new maven project ‘hibernate-enum-attribute-converter-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-enum-attribute-converter-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('M'), FEMALE('F');
private final char code;
Gender(char code) {
this.code = code;
}
public static Gender fromCode(char genderCode) {
if (genderCode == 'F' || genderCode == 'f') {
return FEMALE;
}
if (genderCode == 'M' || genderCode == 'm') {
return MALE;
}
throw new UnsupportedOperationException("The code " + genderCode + " is not supported!");
}
public char getCode() {
return code;
}
}
Step 4: Define GenderConverter class.
GenderConverter.java
package com.sample.app.converters;
import com.sample.app.enums.Gender;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter
public class GenderConverter implements AttributeConverter<Gender, Character> {
@Override
public Character convertToDatabaseColumn(Gender gender) {
if (gender == null) {
return null;
}
return gender.getCode();
}
@Override
public Gender convertToEntityAttribute(Character genderCode) {
if (genderCode == null) {
return null;
}
return Gender.fromCode(genderCode);
}
}
Step 5: Define Person entity class.
Person.java
package com.sample.app.entity;
import com.sample.app.converters.GenderConverter;
import com.sample.app.enums.Gender;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "person")
public class Person {
@Id
private Integer id;
private String name;
@Convert(converter = GenderConverter.class)
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 6: 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 7: 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 the console.
Aug 12, 2022 12:31:23 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 12, 2022 12:31:23 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 12, 2022 12:31:23 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.postgresql.Driver
Aug 12, 2022 12:31:23 PM 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 12:31:23 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=postgres}
Aug 12, 2022 12:31:23 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 12, 2022 12:31:23 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 20 (min=1)
Aug 12, 2022 12:31:24 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Aug 12, 2022 12:31:24 PM 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 12:31:24 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@1b7332a7] 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 char(1),
name varchar(255),
primary key (id)
)
Aug 12, 2022 12:31:24 PM 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
(?, ?, ?)
Query person table to confirm the same.
test=# SELECT * FROM person;
id | gender | name
----+--------+--------
1 | M | Srinu
2 | F | Swetha
(2 rows)
You can download the application from this link.
Previous Next Home
No comments:
Post a Comment