Wednesday, 30 November 2022

Hibernate 6: map class references to VARCHAR type

Hibernate map class references to VARCHAR type.

 

Example

// mapped as VARCHAR
private Class<?> clazz;

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

 

Step 1: Create new maven project ‘hibernate-map-class-ref-to-varchar’.

 

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-map-class-ref-to-varchar</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>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>2.1.214</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 Employee model class.

 

Employee.java

package com.sample.app.dto;

import java.io.Serializable;

public class Employee implements Serializable {

	private static final long serialVersionUID = 1968745L;
	
	private int id;
	private String name;

	public Employee() {
	}

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

	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;
	}

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

}

Step 4: Define SerializedData class.

 

SerializedData.java

package com.sample.app.entity;

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

@Entity
@Table(name = "serialized_data")
public class SerializedData {
	@Id
	private int id;

	private Class<?> clazz;

	private byte[] serializedData;

	public SerializedData(int id, Class<?> clazz, byte[] serializedData) {
		this.id = id;
		this.clazz = clazz;
		this.serializedData = serializedData;
	}

	public int getId() {
		return id;
	}

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

	public Class<?> getClazz() {
		return clazz;
	}

	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}

	public byte[] getSerializedData() {
		return serializedData;
	}

	public void setSerializedData(byte[] serializedData) {
		this.serializedData = serializedData;
	}

}

Step 5: Define SerializationUtil class.

 

SerializationUtil.java

package com.sample.app.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class SerializationUtil {

	public static byte[] serialize(Serializable serializable) {

		try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
				ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
			objectOutputStream.writeObject(serializable);
			objectOutputStream.flush();
			return byteArrayOutputStream.toByteArray();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	public static <T> T deserialize(byte[] byteArray, Class<T> clazz) {
		try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
				ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {
			return (T) objectInputStream.readObject();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

}

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>
		<!-- JDBC Database connection settings -->
		<property name="connection.driver_class">org.h2.Driver</property>
		<property name="connection.url">jdbc:h2:mem:test</property>
		<property name="connection.username">admin</property>
		<property name="connection.password">admin</property>
		<property name="connection.pool_size">1</property>

		<property name="dialect">org.hibernate.dialect.H2Dialect</property>
		<!-- Echo the SQL to stdout -->
		<property name="show_sql">true</property>
		<property name="format_sql">true</property>
		<property name="current_session_context_class">thread</property>
		<!-- Drop and re-create the database schema on startup -->
		<property name="hbm2ddl.auto">create-drop</property>
		
		<!-- dbcp connection pool configuration -->
		<property name="hibernate.dbcp.initialSize">2</property>
		<property name="hibernate.dbcp.maxTotal">10</property>
		<property name="hibernate.dbcp.maxIdle">5</property>
		<property name="hibernate.dbcp.minIdle">3</property>
		<property name="hibernate.dbcp.maxWaitMillis">-1</property>

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

	</session-factory>

</hibernate-configuration>

Step 7: Define main application class.

 

App.java

package com.sample.app;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

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.Employee;
import com.sample.app.entity.SerializedData;
import com.sample.app.util.SerializationUtil;

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

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

	private static <T> List<T> loadAllData(Class<T> clazz, Session session) {
		final CriteriaBuilder builder = session.getCriteriaBuilder();
		final CriteriaQuery<T> 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[]) throws ClassNotFoundException, IOException, URISyntaxException {

		Employee emp1 = new Employee(1, "Krishna");

		byte[] empByteArray = SerializationUtil.serialize(emp1);

		SerializedData d1 = new SerializedData(1, Employee.class, empByteArray);

		try (Session session = sessionFactory.openSession()) {
			session.beginTransaction();
			session.persist(d1);
			session.flush();
			session.getTransaction().commit();

			List<SerializedData> serializedElements = loadAllData(SerializedData.class, session);
			for (SerializedData serializedData : serializedElements) {

				Class clazz = serializedData.getClazz();
				byte[] serializedByteArray = serializedData.getSerializedData();

				System.out.println("id : " + serializedData.getId());
				System.out.println("class : " + clazz);
				System.out.println("object : " + SerializationUtil.deserialize(serializedByteArray, clazz));
			}

		}

	}
}

Total project structure looks like below.




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

Aug 18, 2022 3:18:48 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.h2.Driver
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:h2:mem:test]
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=admin}
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 1 (min=1)
Aug 18, 2022 3:18:49 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Aug 18, 2022 3:18:49 PM org.hibernate.metamodel.internal.EntityInstantiatorPojoStandard resolveConstructor
INFO: HHH000182: No default (no-argument) constructor for class: com.sample.app.entity.SerializedData (class must be instantiated by Interceptor)
Hibernate: 
    
    drop table if exists serialized_data cascade 
Aug 18, 2022 3:18:49 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@1b6924cb] 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 serialized_data (
       id integer not null,
        clazz varchar(255),
        serializedData varbinary(255),
        primary key (id)
    )
Aug 18, 2022 3:18:49 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@6f798482] 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: 
    insert 
    into
        serialized_data
        (clazz, serializedData, id) 
    values
        (?, ?, ?)
Hibernate: 
    select
        s1_0.id,
        s1_0.clazz,
        s1_0.serializedData 
    from
        serialized_data s1_0
id : 1
class : class com.sample.app.dto.Employee
object : Employee [id=1, name=Krishna]

You can download this application from this link.

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment