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