Hibernate Binary Data and BLOB Mapping Example

This tutorial shows you how to map byte array (byte[]) or Binary Large Object (java.sql.Blob) of Java type to database type using Hibernate ORM framework. Byte array or Blob can be used to store large binary data such as files and images. According to Hibernate Types:

 

  • A primitive byte[] is mapped to a JDBC VARBINARY.
  • A java.sql.Blob is mapped to a JDBC BLOB.

Let’s understand how to do binary types mapping by exploring the below sample application. We cover both mapping of byte[] and java.sql.Blob with some slightly differences.

 

1. Database Setup

We are going to code an example program that works with a MySQL database. Therefore, execute the following script to create a database called person_db and a table called person:

 

 

CREATE DATABASE `person_db`;
 
CREATE TABLE `person` (
  `person_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `photo` longblob,
  PRIMARY KEY (`person_id`)
)
 
 

 Here, the column photo is declared as of type longblob in MySQL which can hold approximately up to 232 bytes of data (about 4GB).

 

2. Model Class

Model Class with a primitive byte[] type:

 

Here’s the model class (Person.java) that uses JPA annotations for mapping:

 

package net.codejava.hibernate;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
 
 
@Entity
@Table(name = "PERSON")
public class Person {
    private int id;
    private String name;
    private byte[] photo;
 
    public Person() {
    }
 
    public Person(String name) {
        this.name = name;
    }
 
    @Id
    @Column(name = "PERSON_ID")
    @GeneratedValue
    public int getId() {
        return id;
    }
 
    public byte[] getPhoto() {
        return photo;
    }
 
    public void setPhoto(byte[] photo) {
        this.photo = photo;
    }
 
    // other getters and setters
}
 
Model Class with a java.sql.Blob type:

 

Here’s another version of the model class in case the java.sql.Blob type is used:
 
package net.codejava.hibernate;
 
import java.sql.Blob;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
 
 
@Entity
@Table(name = "PERSON")
public class Person {
    private int id;
    private String name;
    private Blob photo;
 
    public Person() {
    }
 
    public Person(String name) {
        this.name = name;
    }
 
    @Id
    @Column(name = "PERSON_ID")
    @GeneratedValue
    public int getId() {
        return id;
    }
 
    public Blob getPhoto() {
        return photo;
    }
 
    public void setPhoto(Blob photo) {
        this.photo = photo;
    }
 
    // other getters and setters
}
 
XML Mapping

 

In both cases, we can use XML mapping as in the following file (Person.hbm.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.codejava.hibernate">
    <class name="Person" table="PERSON_PHOTO">
        <id name="id" column="PERSON_ID">
            <generator class="native"/>
        </id>
        <property name="name" column="NAME" />
        <property name="photo" column="PHOTO" />
    </class>
</hibernate-mapping>

 

 
 
 

 

Hibernate can infer the actual type of the photo attribute by parsing the Person class. In case we want more verbose, add typeattribute as following:

 

  • For primitive byte[] array:
  • <property name="photo" column="PHOTO" type="binary" />
  • 1
     
  • For java.sql.Blob:
  • <property name="photo" column="PHOTO" type="blob" />
    1
     
It’s better to let Hibernate decides the appropriate mapping type.

 

 

 



If you are new to Hibernate and want to learn more, read this book: Hibernate Made Easy: Simplified Data Persistence with Hibernate and JPA (Java Persistence API) Annotations

 

 

 

3.Test Programs

Here is code of a test program for the case in which a primitive byte[] array is used:
package net.codejava.hibernate;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
 
/**
 * Test Hibernate binary data mapping with primitive byte[] array.
 * @author www.codejava.net
 *
 */
public class PersonPhotoTest {
    private static ServiceRegistry serviceRegistry;
    private static Session session;
     
    public static void main(String[] args) throws IOException {
        initSession();
         
        String photoFilePathToRead = "e:/Test/Photo/Puppy.jpg";
        savePersonWithPhoto(photoFilePathToRead);
         
        int personId = 1;
        String photoFilePathToSave = "e:/Test/Photo/MyPuppy.jpg";
        readPhotoOfPerson(personId, photoFilePathToSave);
         
        endSession();
    }
     
    private static void savePersonWithPhoto(String photoFilePath) throws IOException {
        Person person = new Person("Tom");
        byte[] photoBytes = readBytesFromFile(photoFilePath);
        person.setPhoto(photoBytes);
        session.save(person);
    }
     
    private static void readPhotoOfPerson(int personId, String photoFilePath) throws IOException {
        Person person = (Person) session.get(Person.class, personId);
        byte[] photoBytes = person.getPhoto();
        saveBytesToFile(photoFilePath, photoBytes);
    }
     
    private static byte[] readBytesFromFile(String filePath) throws IOException {
        File inputFile = new File(filePath);
        FileInputStream inputStream = new FileInputStream(inputFile);
         
        byte[] fileBytes = new byte[(int) inputFile.length()];
        inputStream.read(fileBytes);
        inputStream.close();
         
        return fileBytes;
    }
     
    private static void saveBytesToFile(String filePath, byte[] fileBytes) throws IOException {
        FileOutputStream outputStream = new FileOutputStream(filePath);
        outputStream.write(fileBytes);
        outputStream.close();
    }
     
     
    private static void initSession() {
        Configuration configuration = new Configuration().configure();
        serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(configuration.getProperties()).build();
         
        SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
         
        session = sessionFactory.openSession();
        session.beginTransaction();
    }
     
    private static void endSession() {
        session.getTransaction().commit();
        session.close();
         
        StandardServiceRegistryBuilder.destroy(serviceRegistry);       
    }
 
}

 

 
 
And the following program’s code is for the case in which a java.sql.Blob is used:

 

package net.codejava.hibernate;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Blob;
import java.sql.SQLException;
 
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
 
/**
 * Test Hibernate binary data mapping with java.sql.Blob type.
 * @author www.codejava.net
 *
 */
public class PersonPhotoTest {
    private static ServiceRegistry serviceRegistry;
    private static Session session;
     
    public static void main(String[] args) throws IOException, SQLException {
        initSession();
         
        String photoFilePathToRead = "e:/Test/Photo/Rex10.jpg";
        savePersonWithPhoto(photoFilePathToRead);
         
        endSession();
         
        initSession();
         
        int personId = 1;
        String photoFilePathToSave = "e:/Test/Photo/MyPuppy.jpg";
        readPhotoOfPerson(personId, photoFilePathToSave);
         
        endSession();
    }
     
    private static void savePersonWithPhoto(String photoFilePath) throws IOException, SQLException {
        Person person = new Person("Peter");
        File file = new File(photoFilePath);
        FileInputStream inputStream = new FileInputStream(file);
        Blob blob = Hibernate.getLobCreator(session)
                            .createBlob(inputStream, file.length());
        person.setPhoto(blob);
        session.save(person);
        blob.free();
    }
     
    private static void readPhotoOfPerson(int personId, String photoFilePath) throws IOException, SQLException {
        Person person = (Person) session.get(Person.class, personId);
        Blob blob = person.getPhoto();
        byte[] blobBytes = blob.getBytes(1, (int) blob.length());
        saveBytesToFile(photoFilePath, blobBytes);
        blob.free();
    }
     
    private static void saveBytesToFile(String filePath, byte[] fileBytes) throws IOException {
        FileOutputStream outputStream = new FileOutputStream(filePath);
        outputStream.write(fileBytes);
        outputStream.close();
    }
     
    private static void initSession() {
        Configuration configuration = new Configuration().configure();
        serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(configuration.getProperties()).build();
         
        SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
         
        session = sessionFactory.openSession();
        session.beginTransaction();
    }
     
    private static void endSession() {
        session.getTransaction().commit();
        session.close();
         
        StandardServiceRegistryBuilder.destroy(serviceRegistry);       
    }
 
}
 
 
Both of these test programs insert a person with a photo (specified by its file path) to the database, and then they read the person back, extract the photo data and save as an image file. For your convenience, download both projects in the attachments section below.

 

posted @ 2015-08-06 14:57  zhh  阅读(411)  评论(0编辑  收藏  举报