Details Written by Nam Ha Minh Last Updated on 15 July 2019   |   Print Email
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 2
32 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
type attribute as following:
It’s better to let Hibernate decides the appropriate mapping type.
3. Hibernate Blob Mapping 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.
Other Hibernate Tutorials: About the Author: Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on
Facebook and watch
his Java videos on YouTube.
Add comment
Comments
Use longblob type which supports up to 4GB.
which is the best way ,if the size of file is large.2+ GB approx.
JAXB, Web Services, and Binary Data
In my case Im working in an webservice app where I have a field "logo" in a table client. Where I need to store the client's logo image. I used Netbenas MySQL and Hibernate. And I generate POJOS and hbm.xml with the Netbeans wizard.
But Jaxb gives me this error message:
Dec 31, 2015 11:06:10 AM com.sun.xml.bind.v2.runtime.reflect.opt.Injector inject
WARNING: duplicate class definition bug occured? Please report this : com/model/pojos/Organizacion$JaxbAccessorM_getLogo_setLogo_[B
java.lang.ClassFormatError: Illegal class name
where logo Hibernate has mapped it like this:
-In the class:
private byte[] logo;
setter and getter
-In the hbm file:
Please Blaise Help!