Monday, 28 November 2022

Hibernate 6: Example of BLOB, CLOB and NCLOB types

In this post, I am going to explain about the following JDBC LOB locator types.

 

a.   java.sql.Blob

b.   java.sql.Clob

c.    java.sql.NClob

 

Define Blob, Clob and NClob variables using @Lob annotation.

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

    @Lob
    private Clob clob;

    @Lob
    @Nationalized
    private NClob nclob;

    @Lob
    private Blob blob;

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

How to create a Clob object?

You can create a Clob object using ClobProxy.generateProxy() method.

String msg = "Hello World";
Clob clob = ClobProxy.generateProxy(msg);

How to create a NClob object?

You can create a NClob object using NClobProxy.generateProxy() method.

String msg = "Hello World";
NClob nclob = NClobProxy.generateProxy(msg);

How to create a Blob object?

You can create a Blob object using BlobProxy.generateProxy() method.

byte[] byteMsg = "Hello World".getBytes();
Blob blob = BlobProxy.generateProxy(byteMsg);

How to retrieve the Clob content from entity?

To retrieve the Clob content, you need to transform the underlying java.io.Reader.

try (Reader reader = record.getClob().getCharacterStream()) {
    String clobStr = new BufferedReader(reader).lines().collect(Collectors.joining("\n"));
}

How to retrieve the NClob content from entity?

To retrieve the NClob content, you need to transform the underlying java.io.Reader.

try (Reader reader = record.getNclob().getCharacterStream()) {
    String nclobStr = new BufferedReader(reader).lines().collect(Collectors.joining("\n"));
}

How to retrieve the Blob content?

To retrieve the Blob content, you need to transform the underlying binary stream.

try (InputStream is = record.getBlob().getBinaryStream()) {
    String blobStr = new BufferedReader(new InputStreamReader(is)).lines() .collect(Collectors.joining("\n"));
}

We can also map the CLOB, NCLOB and BLOB in a materialized form. You can read my below posts.

a.   How to map a String to CLOB?

b.   How to map a character array to CLOB?

c.    How to map a byte array to BLOB?

 

Find the below working application.

 

Step 1: Create new maven project ‘hibernate-blob-clob-nclob-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-blob-clob-nclob-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>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 entity class.

 

Demo.java

 

package com.sample.app.entity;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;

import org.hibernate.annotations.Nationalized;

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

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

    @Lob
    private Clob clob;

    @Lob
    @Nationalized
    private NClob nclob;

    @Lob
    private Blob blob;

    public Demo(int id, Clob clob, NClob nclob, Blob blob) {
        this.id = id;
        this.clob = clob;
        this.nclob = nclob;
        this.blob = blob;
    }

    public int getId() {
        return id;
    }

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

    public Clob getClob() {
        return clob;
    }

    public void setClob(Clob clob) {
        this.clob = clob;
    }

    public NClob getNclob() {
        return nclob;
    }

    public void setNclob(NClob nclob) {
        this.nclob = nclob;
    }

    public Blob getBlob() {
        return blob;
    }

    public void setBlob(Blob blob) {
        this.blob = blob;
    }

}

 

Step 4: 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="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.Demo" />

    </session-factory>

</hibernate-configuration>

 

Step 5: Define main application class.

 

App.java

 

package com.sample.app;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

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 org.hibernate.engine.jdbc.BlobProxy;
import org.hibernate.engine.jdbc.ClobProxy;
import org.hibernate.engine.jdbc.NClobProxy;

import com.sample.app.entity.Demo;

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

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

    }

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

    public static void main(final String args[]) throws IOException, SQLException {
        // Create a Clob using ClobProxy.
        String msg = "Hello World";
        Clob clob = ClobProxy.generateProxy(msg);
        NClob nclob = NClobProxy.generateProxy(msg);

        byte[] byteMsg = "Hello World".getBytes();
        Blob blob = BlobProxy.generateProxy(byteMsg);

        Demo e1 = new Demo(1, clob, nclob, blob);

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

            session.persist(e1);

            session.flush();
            session.getTransaction().commit();

            List<Demo> records = loadAllData(Demo.class, session);

            for (Demo record : records) {
                int id = record.getId();
                System.out.println("id : " + id);

                try (InputStream is = record.getBlob().getBinaryStream()) {
                    String blobStr = new BufferedReader(new InputStreamReader(is)).lines()
                            .collect(Collectors.joining("\n"));
                    System.out.println("blobStr : " + blobStr);
                }

                try (Reader reader = record.getClob().getCharacterStream()) {
                    String clobStr = new BufferedReader(reader).lines().collect(Collectors.joining("\n"));
                    System.out.println("clobStr : " + clobStr);
                }

                try (Reader reader = record.getNclob().getCharacterStream()) {
                    String nclobStr = new BufferedReader(reader).lines().collect(Collectors.joining("\n"));
                    System.out.println("nclobStr : " + nclobStr);
                }
            }
        }

    }
}

 

Total project structure looks like below.

 

 


 

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

 

Aug 17, 2022 12:48:51 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 6.1.2.Final
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using built-in connection pool (not intended for production use)
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: Loaded JDBC driver class: org.h2.Driver
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001012: Connecting with JDBC URL [jdbc:h2:mem:test]
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=admin}
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH10001115: Connection pool size: 1 (min=1)
Aug 17, 2022 12:48:51 PM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Aug 17, 2022 12:48:52 PM org.hibernate.metamodel.internal.EntityInstantiatorPojoStandard resolveConstructor
INFO: HHH000182: No default (no-argument) constructor for class: com.sample.app.entity.Demo (class must be instantiated by Interceptor)
Hibernate: drop table if exists demo cascade 
Aug 17, 2022 12:48:52 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@22c75c01] 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 demo (id integer not null, blob blob, clob clob, nclob nclob, primary key (id))
Aug 17, 2022 12:48:52 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@5984feef] 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 demo (blob, clob, nclob, id) values (?, ?, ?, ?)
Hibernate: select d1_0.id,d1_0.blob,d1_0.clob,d1_0.nclob from demo d1_0
id : 1
blobStr : Hello World
clobStr : Hello World
nclobStr : Hello World

You can download this application from this link.


 

Previous                                                    Next                                                    Home

No comments:

Post a Comment