Вы находитесь на странице: 1из 136

1

What is Hibernate framework


Hibernate is a Java-based framework that aims at relieving developers from common database
programming tasks such as writing SQL queries manually with JDBC. Thus developers can
focus more on business logic of the application. Hibernate encapsulates common database
operations (CRUD create, retrieve, update and delete) via a set of useful APIs.
Hibernate is also an Object/Relational Mapping (ORM) framework which maps tables from
database with Java objects, allows developers to build database relationship and access data
easily through its mapping, configuration and APIs . It is widely used by Java developers for
Java applications ranging from desktop to enterprise.
If you are new to Hibernate and cant wait to learn it, this tutorial is to you. We will get you
familiar with Hibernate through a hand-on exercise which involves in developing a simple Java
application to manage data of a table in database (IDE to use is Eclipse). You will see how
simple Hibernate makes to database development.
The sample application
In this tutorial, we will develop a console application that manages a list of contacts in MySQL
database. Hibernate will be used to perform the CRUD operations: create, read, update, and
delete. Let's start!
Download Hibernate and MySQL driver
You can obtain the latest distribution of Hibernate framework at:
http://hibernate.org/downloads
You are redirected to SourceForge download page:
http://sourceforge.net/projects/hibernate/files/hibernate4/
At the time of writing this tutorial, the latest version of Hibernate is 4.1.5.SP1. Download the zip
archive hibernate-release-4.1.5.SP1.zip and extract it to a desired location on your computer. The
distribution has a lot of stuff but we are interested in only the required JAR files which are under
lib\required directory:
Those JAR files are minimum requirement for getting started with Hibernate.
In addition, we need to download JDBC driver library for MySQL, called Connector/J at:
http://www.mysql.com/downloads/connector/j/
Extract the mysql-connector-java-5.1.21.zip file and pick up the JAR file mysql-connector-java-
5.1.21-bin.jar.
2

Notes: For more information about downloading and using MySQL JDBC driver, see the
tutorial: Connect to MySQL via JDBC.

Setup database
Suppose that you have MySQL server installed on your computer. Execute the following SQL
script to create a table called contact in database contactdb:
1
2
3
4
5
6
7
8
9
10
11
create database contactdb;
use contactdb;
CREATE TABLE `contact` (
`contact_id` INT NOT NULL ,
`name` VARCHAR(45) NOT NULL ,
`email` VARCHAR(45) NOT NULL ,
`address` VARCHAR(45) NOT NULL ,
`telephone` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`contact_id`) )
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
From the above script, we can see that a contact has following information:
o contact_id: primary key of the table
o name
o email
o address
o telephone.
Setup Eclipse project
Create a new Java project in Eclipse entitled ContactManager.
3

Select Project Properties from main menu.
The dialog Properties for ContactManager appears, select Java Build Path on the left. Under
Libraries tab on the right, click Add External JARs.
In the dialog Jar Selection, select all JAR files under the directory
{Hibernate_Home}\lib\required where {Hibernate_Home} is the directory where you extracted
Hibernate distribution previously.
Click Open to add these JAR files to projects classpath, as shown in the following screen-shot:

In addition, since we use MySQL database, its necessary to include a MySQL JDBC driver
library to the project as well. See this article for how to download and extract MySQL JDBC
driver JAR file.
Under src directory, create a new Java package called com.mycompany
Hibernate configuration file
First of all, you need to tell Hibernate some information regarding the database system you
intend to use, such as host name, port number, JDBC driver class name, database connection
URL via some kind of configuration. Flexibly, Hibernate provides several ways for supplying
database configuration:
4

o via properties file.
o via XML file.
o via JNDI data source.
o Programmatic configuration.
o Setting system properties.
We choose XML configuration file. In Eclipse, create a new XML file under src directory with
this name: hibernate.cfg.xml. Put some configuration information in this file as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/contactdb</property>
<property name="connection.username">root</property>
<property name="connection.password">P@ssw0rd</property>

</session-factory>
</hibernate-configuration>
We specify JDBC class driver name (for MySQL), connection URL (which also specifies host
name, port number, and database name), user name and password to connect to the database.
The class org.hibernate.cfg.Configuration is used to load the configuration file:
1 Configuration conf = new Configuration().configure();
The configure() method reads configuration from hibernate.cfg.xml file under programs
classpath.
There are also some overloaded versions of configure() method which allow you to load
configuration file in different ways.
The above configuration is only for necessary information. In addition, Hibernate provides a
variety of settings such as connection pooling, transaction, debugging however we dont cover
all of them in this simple tutorial. Just add this line to the hibernate.cfg.xml file:
1 <property name="show_sql">true</property>
which tells Hibernate to show all SQL statements to the standard output.

5

Create Java entity class
Next, we will create a plain old java object (POJO) class which represents a table in the database.
Since we created a table called Contact, we also create a new Java class with the same name,
Contact.java, under package com.mycompany. Write code for the Contact class as following:
package com.mycompany;
public class Contact {
private int id;
private String name;
private String email;
private String address;
private String telephone;
public Contact() {
}
public Contact(int id, String name, String email, String address,
String telephone) {
this.id = id;
this.name = name;
this.email = email;
this.address = address;
this.telephone = telephone;
}
public Contact(String name, String email, String address, String telephone) {
this.name = name;
this.email = email;
this.address = address;
this.telephone = telephone;
}
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;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
6

}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
}
Its just a simple class following JavaBean naming convention.
Create mapping file
Hibernate can detect Java classes which map with tables in the database via some kind of
mappings. A mapping tells Hibernate how to map between a Java class and a table in the
database. For example, the class maps with which table, which class member maps with which
field in that table, what kind of data types, etc.
Hibernate allows developer to specify mapping through XML file or annotations embedded right
in the Java source file. We go with the XML mapping.
In Eclipse, create a new XML file called Contact.hbm.xml under package com.mycompany, with
the following content:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.mycompany">
<class name="Contact" table="CONTACT">
<id name="id" column="CONTACT_ID">
<generator class="increment"/>
</id>
<property name="name" type="string" column="NAME"/>
<property name="email"/>
<property name="address"/>
<property name="telephone"/>

</class>
</hibernate-mapping>
7

As you can see:
The package property of the root element <hibernate-mapping> specifies
under which package Hibernate finds Java classes.
The class element specifies which Java class (via property name) maps with
which table (via property table) in the database.
The id element specifies which property in the Java class map to primary
key column in the database. The generator element tells Hibernate how the
primary keys value is created, and we specify increment which means the value
is incremented automatically.
The propertyelement specifies how a property in the Java class maps with a
column in the database:
the name property specifies name of a property in Java class.
the column property specifies mapping column in database.
the type property specifies data type of the mapping column. By
default, Hibernate can detect and create mapping automatically based on
property name and the JavaBean class, so you can see, we do not specify
type and column for the last three properties.
After defining the mapping file, you need to tell Hibernate to parse the mapping file by adding
the following entry in the hibernate.cfg.xml file:
1 <mapping resource="com/mycompany/Contact.hbm.xml"/>
The hibernate.cfg.xml file should look like this till now:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/contactdb</property>
<property name="connection.username">root</property>
<property name="connection.password">P@ssw0rd</property>

<property name="show_sql">true</property>

<mapping resource="com/mycompany/Contact.hbm.xml"/>

</session-factory>
</hibernate-configuration>

8

Working with Hibernate session
Hibernate provides its database services via a session. In other words, all database operations are
executed under context of a Hibernate session. The session manages mapped objects and offers
databases CRUD (create, read, update, delete) operations. Working with Hibernates API
involves in working with its Session and Sessions relevant methods.
The following code obtains a new session from a session factory:
1
2
3
4
5
6
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.openSession();
The Session interface defines a number of methods for executing CRUD operations with
mapped objects. The following table lists the most common methods provided by the session:
# Method name Return Description Issued SQL
statement
1 beginTransaction() Transaction Creates a Transaction object or
returns an existing one, for
working under context of a
transaction.

2 getTransaction() Transaction Returns the current transaction.
3 get(Class class,
Serializable id)
Object Loads a persistent instance of the
given class with the given id, into
the session.
SELECT
4 load(Class class,
Serializable id)
Object Does same thing as get() method,
but throws an ObjectNotFound
error if no row with the given id
exists.
SELECT
5 persist(Object) void saves a mapped object as a row in
database
INSERT
6 save(Object) Serializable Does same thing as persist()
method, plus returning a
generated identifier.
INSERT
7 update(Object) void Updates a detached instance of
the given object and the
underlying row in database.
UPDATE
8 saveOrUpdate(Object) void Saves the given object if it does
not exist, otherwise updates it.
INSERT or
UPDATE
9 delete(Object) void Removes a persistent object and
the underlying row in database.
DELETE
10 close() void Ends the current session.
9

11 flush() void Flushes the current session. This
method should be called before
committing the transaction and
closing the session.

12 disconnect() void Disconnects the session from
current JDBC connection.


Working with Hibernate transaction
Multiple database operations should be executed inside a transaction in order to protect
consistence of data in the database in case of exceptions or errors occurred. The following
skeleton code illustrates working with a transaction in Hibernate:
1
2
3
4
5
6
7
8
9
10
session.beginTransaction();
try {
session.persist(Object);
session.update(Object);
session.delete(Object);
} catch (Exception ex) {
session.getTransaction().rollback();
}
session.getTransaction().commit();
session.close();
When working with transaction, it requires committing the transaction to make permanent
changes to the database, and finally, close the session.
Perform CRUD operations with Hibernate
Create:
To persist an object into the session (equivalent to inserting a record into the database),
either persist()or save() method can be used. For example:
1
2
3
4
5
Contact contact1 = new Contact("Nam", "hainatuatgmail.com", "Vietnam", "0904277091");
session.persist(contact1);
Contact contact2 = new Contact("Bill", "billatgmail.com", "USA", "18001900");
Serializable id = session.save(contact2);
System.out.println("created id: " + id);
The save method returns id of the new record inserted in the database.
Read:
10

To retrieve a persistent object from the database into the session (equivalent to selecting a record
from the database), use the get() method. For example:
1
2
3
4
5
6
Contact contact = (Contact) session.get(Contact.class, new Integer(2));
if (contact == null) {
System.out.println("There is no Contact object with id=2");
} else {
System.out.println("Contact3's name: " + contact.getName());
}
The get()method returns null if there is no row with the given id exists in the database, whereas
the load() method throws an ObjectNotFound error. Therefore, use the load() method only when
the object is assumed exists.
Update:
To update a persistent object which is already loaded in the session (attached instance),
simply update the mapped object. Hibernate will update changes to the database then the
session is flushed. For example:
1
2
3
Contact contact = (Contact) session.load(Contact.class, new Integer(5));
contact.setEmail("infoatcompany.com");
contact.setTelephone("1234567890");
You can call the update() method explicitly (but not required):
1 session.update(contact);
To update a detached instance, call either the update() or saveOrUpdate() method, for
example:
1
2
Contact contact = new Contact("Jobs", "jobsatapplet.com", "Cupertino", "0123456789");
session.update(contact);
Both the update() or saveOrUpdate() methods throws a NonUniqueObjectException
exception if there is a different object with the same identifier value was already
associated with the session. For example, the update() statement in the following code
throws such exception:
1
2
3
Contact contact = (Contact) session.load(Contact.class, new Integer(3));
Contact contactUpdate = new Contact(3, "Jobs", "jobsatapplet.com", "Cupertino",
"0123456789");
session.update(contactUpdate); // will throw NonUniqueObjectException
Delete:
11

To delete an object with a given identifier, use the delete() method, for example:
1
2
3
Contact contactToDelete = new Contact();
contactToDelete.setId(4);
session.delete(contactToDelete);
or delete a loaded instance:
1
2
Contact contactToDelete = (Contact) session.load(Contact.class, new Integer(4));
session.delete(contactToDelete);
The delete() method throws a StaleStateException exception if there is no row with the
given identifier exists in the database, and a NonUniqueObjectException exception if
there is a different object with the same identifier value was already associated with the
session.
Write the sample program
Finally, we write the sample program to demonstrate how to perform CRUD operations with
Hibernate. In Eclipse IDE, create a new class called ContactManager under package
com.mycompany with the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.mycompany;

import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
* A sample program that demonstrates how to perform simple CRUD operations
* with Hibernate framework.
* @author www.codejava.net
*
*/
public class ContactManager {
public static void main(String[] args) {
// loads configuration and creates a session factory
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

12

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// opens a new session from the session factory
Session session = sessionFactory.openSession();
session.beginTransaction();
// persists two new Contact objects
Contact contact1 = new Contact("Nam", "hainatuatgmail.com", "Vietnam",
"0904277091");
session.persist(contact1);
Contact contact2 = new Contact("Bill", "billatgmail.com", "USA", "18001900");
Serializable id = session.save(contact2);
System.out.println("created id: " + id);

// loads a new object from database
Contact contact3 = (Contact) session.get(Contact.class, new Integer(1));
if (contact3 == null) {
System.out.println("There is no Contact object with id=1");
} else {
System.out.println("Contact3's name: " + contact3.getName());
}

// loads an object which is assumed exists
Contact contact4 = (Contact) session.load(Contact.class, new Integer(4));
System.out.println("Contact4's name: " + contact4.getName());

// updates a loaded instance of a Contact object
Contact contact5 = (Contact) session.load(Contact.class, new Integer(5));
contact5.setEmail("info1atcompany.com");
contact5.setTelephone("1234567890");
session.update(contact5);
// updates a detached instance of a Contact object
Contact contact6 = new Contact(3, "Jobs", "jobsatapplet.com", "Cupertino",
"0123456789");
session.update(contact6);

// deletes an object
Contact contact7 = new Contact();
contact7.setId(7);
session.delete(contact7);
// deletes a loaded instance of an object
Contact contact8 = (Contact) session.load(Contact.class, new Integer(8));
session.delete(contact8);

// commits the transaction and closes the session
session.getTransaction().commit();
session.close();

}}
13


As you can see, there are no SQL statements have to be written to interact with the database,
because Hibernate hides all the complex details and exposes its simple and intuitive API. Thus
you are free of writing repetitive SQL queries and check their syntax. Working with Hibernate
will involve mainly with defining the entities, the mapping, and the association among entities in
your application.
The projects structure looks like the following screenshot:

Run the program
Right click on the ContactManager.java file, select Run As > Java Application. The program
produces some output in Eclipses Console view, as in the following screenshot:
As you can see, the text in red is the debugging information of Hibernate, the text in black is the
programs output, and we can see Hibernate issues these SQL statements: select, insert, update
and delete.

14


Download Eclipse project
You can download the sample application as an Eclipse project in the attachment section at the
end of this tutorial.











15

Hibernate One-to-Many Using Join Table XML Mapping Example
In this Hibernate tutorial, we will learn how to use XML to map a one-to-many association on
join table in relational database with Java objects. The following entity relationship diagram
depicts the association:

One-to-Many association on a join table
Here, a category can contain from one to many occurrences of article. The CategoryArticle is
the join table between them. Lets see how to model this association in Hibernate framework.
The sample application in this tutorial was developed and tested in the following environment:
o Hibernate 4.2.2.Final
o JDK 7
o Eclipse IDE 4.2 (Juno)
o MySQL Community Server 5.5.23
o MySQL Connector Java driver 5.1.25
Table of content:
1. Creating Database Tables
2. Setting up an Eclipse Project
3. Coding Hibernate Model Classes
4. Writing Hibernate Mapping Files
5. Writing Hibernate Configuration File
6. Coding a Test Program
1. Creating Database Tables
Create a MySQL database called newsdb with three tables: category, article and
CategoryArticle (join table), by executing the following script in MySQL Workbenchs SQL
Editor:
1 CREATE DATABASE `newsdb`;
16

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

use newsdb;

CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`)
);


CREATE TABLE `article` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(70) NOT NULL,
`description` varchar(250) NOT NULL,
`keywords` varchar(150) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`article_id`)
);


CREATE TABLE `categoryarticle` (
`category_id` int(11) NOT NULL,
`article_id` int(11) NOT NULL,
PRIMARY KEY (`category_id`,`article_id`),
KEY `fk_category` (`category_id`),
KEY `fk_article` (`article_id`),
CONSTRAINT `fk_article` FOREIGN KEY (`article_id`) REFERENCES `article`
(`article_id`),
CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category`
(`category_id`)
);
If you are using MySQL Command Line Client, type the following command:
source Path\To\The\Script\File\MySQLscript.sql
Create the MySQLscript.sql file from the above script or find it in the attached project. The
database newsdb will have the following structure:
17


2. Setting up an Eclipse Project
Create a Java project in Eclipse IDE called HibernateOne2ManyJoinTableXMLExample with
the following structure:
18

We will create/add to this project the following files:
o Model classes: Category.java and Article.java
o Hibernate XML mapping files: Category.hbm.xml and Article.hbm.xml
o Hibernate XML configuration file: hibernate.cfg.xml
o Test program: ArticlesManager.java
o Hibernate required JAR libraries and MySQL Connector Java driver:
hibernate-core-4.2.2.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
mysql-connector-java-5.1.25-bin.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jboss-logging-3.1.0.GA.jar
antlr-2.7.7.jar
dom4j-1.6.1.jar
javassist-3.15.0-GA.jar
o MySQL script file: MySQLscript.sql
Find the Hibernate and MySQL jar files from their distribution archives.
3. Coding Hibernate Model Classes
Create two Java files Category.java and Article.java corresponding to the tables category and
article:
File net\codejava\hibernate\Category.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package net.codejava.hibernate;

import java.util.Set;

public class Category {

private long id;
private String name;

private Set<Article> articles;

public Category() {
}

public Category(String name) {
this.name = name;
}
19

18
19
20

// getters and setters...
}
File net\codejava\hibernate\Article.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package net.codejava.hibernate;

public class Article {
private long id;
private String title;
private String description;
private String keywords;
private String content;

private Category category;

public Article() {
}

public Article(String title, String description, String keywords,
String content, Category category) {
this.title = title;
this.description = description;
this.keywords = keywords;
this.content = content;
this.category = category;
}

// getters and setters...
}
NOTES: The Category class has a set of articles and the Article class has a reference to its
category. This is a typical configuration for a bidirectional one-to-many association. And note
that we dont have to write model class for the join table.
4. Writing Hibernate Mapping Files
Create two Hibernate mapping files Category.hbm.xml and Article.hbm.xml with the following
content:
File net\codejava\hibernate\Category.hbm.xml:
1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
20

4
5
6
7
8
9
10
11
12
13
14
15
16
17
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.codejava.hibernate">
<class name="Category" table="CATEGORY">
<id name="id" column="CATEGORY_ID">
<generator class="native"/>
</id>
<property name="name" column="NAME" />

<set name="articles" table="CategoryArticle" cascade="all">
<key column="CATEGORY_ID" not-null="true" />
<many-to-many column="ARTICLE_ID" class="Article" unique="true"/>
</set>
</class>
</hibernate-mapping>
File net\codejava\hibernate\Article.hbm.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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="Article" table="ARTICLE">
<id name="id" column="ARTICLE_ID">
<generator class="native"/>
</id>
<property name="title" column="TITLE" />
<property name="description" column="DESCRIPTION" />
<property name="keywords" column="KEYWORDS" />
<property name="content" column="CONTENT" />

<join table="CategoryArticle" inverse="true">
<key column="ARTICLE_ID"/>
<many-to-one name="category" column="CATEGORY_ID" not-null="true"/>
</join>
</class>
</hibernate-mapping>
NOTES:
o We specify the join table CategoryArticle for both sides, in the <set> element of
the Category.hbm.xml file and in the <join> element of the Article.hbm.xml file.
o Category.hbm.xml: The attribute cascade=all tells Hibernate to update changes
to the children (article) automatically when the parent (category) has changed.
21

o Article.hbm.xml: The attribute inverse=true tells Hibernate that the
relationship owner is on the reverse side (the join table). Specifying this attribute
is required for a one-to-many association.
5. Writing Hibernate Configuration File
Write code for the Hibernate configuration file (hibernate.cfg.xml) as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/newsdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping resource="net/codejava/hibernate/Category.hbm.xml"/>
<mapping resource="net/codejava/hibernate/Article.hbm.xml"/>

</session-factory>
</hibernate-configuration>
You may need to change the username and password according to your MySQL account.
6. Coding a Test Program
To wire all the above pieces together, create a test program that persists some sample data as
follows:
1
2
3
4
5
6
7
8
9
10
11
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

22

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* This program demonstrates how to use Hibernate framework to manage
* a one-to-many association on a join table.
* @author www.codejava.net
*
*/
public class ArticlesManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration
.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Category category = new Category("Hibernate Framework");

Article articleOne = new Article("One-to-One Mapping",
"One-to-One XML Mapping Tutorial", "Hibernate,One-to-One",
"Content of One-to-One XML Mapping Tutorial", category);
Article articleTwo = new Article("One-to-Many Mapping",
"One-to-Many XML Mapping Tutorial", "Hibernate,One-to-Many",
"Content of One-to-Many XML Mapping Tutorial", category);
Article articleThree = new Article("Many-to-Many Mapping",
"Many-to-Many XML Mapping Tutorial", "Hibernate,Many-to-Many",
"Content of Many-to-Many XML Mapping Tutorial", category);

Set<Article> articles = new HashSet<Article>();
articles.add(articleOne);
articles.add(articleTwo);
articles.add(articleThree);

category.setArticles(articles);

session.save(category);

session.getTransaction().commit();
session.close();
23

58
59
60
}

}
Output of the program:
Hibernate: insert into CATEGORY (NAME) values (?)
Hibernate: insert into ARTICLE (TITLE, DESCRIPTION, KEYWORDS, CONTENT)
values (?, ?, ?, ?)
Hibernate: insert into ARTICLE (TITLE, DESCRIPTION, KEYWORDS, CONTENT)
values (?, ?, ?, ?)
Hibernate: insert into ARTICLE (TITLE, DESCRIPTION, KEYWORDS, CONTENT)
values (?, ?, ?, ?)
Hibernate: insert into CategoryArticle (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Hibernate: insert into CategoryArticle (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Hibernate: insert into CategoryArticle (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Result in the category table:

Result in the article table:

Result in the CategoryArticle table:



24

Getting Started With Hibernate Annotations
Table of content:
1. Whats in this tutorial?
2. When to use annotations?
3. Quick reference on annotations used
4. Tools needed
5. Project Structure
6. Setup Database Configuration
7. Create annotated model classes
8. Create Database
9. Writing Test Program
1. Whats in this tutorial?
Well setup a sample Hibernate application here which demonstrates the usage of annotations.
o Create a database connection configuration using XML
o Create model classes Person and Address and establish a many-to-many
relationship between them and map them with database using annotations
o Obtain connection using Configuration object and build a SessionFactory object
o Obtain Session objects to perform a save operation using Hibernate APIs
2. When to use annotations?
Use annotations to provide metadata configuration along with the Java code. That way the code
is easy to understand. Annotations are less powerful than XML configuration. XML also gives
you the ability to change the configuration without building the project. So use annotations only
for table and column mappings, not for frequently changing stuff like database connection and
other properties. Annotations are preconfigured with sensible default values, which reduce the
amount of coding required, e.g. class name defaults to table name and field names defaults to
column names.
3. Quick reference on annotations used

Annotation Modifier Description
@Entity Marks a class as a Hibernate Entity (Mapped
class)
@Table Name Maps this class with a database table specified
by name modifier. If name is not supplied it
maps the class with a table having same name
as the class
@Id Marks this class field as a primary key column
25

@GeneratedValue Instructs database to generate a value for this
field automatically
@Column Name Maps this field with table column specified by
name and uses the field name if name modifier
is absent


@ManyToMany
Cascade Marks this field as the owning side of the
many-to-many relationship and cascade
modifier specifies which operations should
cascade to the inverse side of relationship
mappedBy This modifier holds the field which specifies
the inverse side of the relationship




@JoinTable
Name For holding this many-to-many relationship,
maps this field with an intermediary database
join table specified by name modifier
joinColumns Identifies the owning side of columns which are
necessary to identify a unique owning object
inverseJoinColumns Identifies the inverse (target) side of columns
which are necessary to identify a unique target
object
@JoinColumn Name Maps a join column specified by the name
identifier to the relationship table specified by
@JoinTable
4. Tools needed
o Download latest version of Eclipse: http://www.eclipse.org/downloads
o Download latest JDK:
http://www.oracle.com/technetwork/java/javase/downloads/index.html
o Download latest MySQL: http://dev.mysql.com/downloads/mysql
o Download latest Hibernate distribution zip:
http://sourceforge.net/projects/hibernate/files/hibernate4 (Hibernate 4.1.9 as of
writing)
o Lets presume youve unzipped the Hibernate distribution zip to a directory called
Hibernate. You would need all the jar files under Hibernate\lib\required and
Hibernate\lib\jpa directories
o MySQL Java Connector Jar: http://dev.mysql.com/downloads/connector/j
Recommended Book: Java Persistence with Hibernate
5. Project Structure
26


6. Setup Database Configuration
Create hibernate.cfg.xml file as shown in above figure and configure the database connection
and mapping classes. Here is the XML configuration:
1
2
3
4
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
27

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

<hibernate-configuration>
<session-factory>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<property name="use_sql_comments">false</property>

<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property
name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/hibernateTutorial</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">secret</property>

<!-- add classes to map from here -->
<mapping class="net.codejava.hibernate.model.Person" />
<mapping class="net.codejava.hibernate.model.Address" />
</session-factory>
</hibernate-configuration>
Here we instructed Hibernate to connect to a MySQL database named hibernateTutorial. As you
can see, we supplied database URL, username and password for the connection. We also
instructed Hibernate to use MySQLDialect i.e. Hibernate will optimize the generated SQL
statements for MySQL. We also added couple of entities called Person and Address which well
configure later. This configuration will be used to create a Hibernate SessionFactory object.
7. Create annotated model classes
Create model classes Person.java and map it to the database using annotations as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package net.codejava.hibernate.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
28

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
@Table(name = "person")
public class Person {

long id;
String firstName;
String lastName;
Set<Address> addresses;

public Person() {

}

public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.addresses = new HashSet<Address>();
}

@Id
@GeneratedValue
@Column(name = "person_id")
public long getId() {
return id;
}

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

@Column
public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

@Column
public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}
29

63
64
65
66
67
68
69
70
71
72
73
74

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(name = "person_address", joinColumns = { @JoinColumn(name =
"person_id") }, inverseJoinColumns = { @JoinColumn(name = "address_id") })
public Set<Address> getAddresses() {
return addresses;
}

public void setAddresses(Set<Address> addresses) {
this.addresses = addresses;
}

}
Create model classes Address.java and map it to the database using annotations as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.codejava.hibernate.model;

import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "address")
public class Address {

long id;
String buildingName;
String town;
String postCode;
Set<Person> persons;

public Address() {

}

public Address(String buildingName, String town, String postCode) {
this.buildingName = buildingName;
this.town = town;
this.postCode = postCode;
}
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

@Id
@GeneratedValue
@Column(name = "address_id")
public long getId() {
return id;
}

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

@Column
public String getBuildingName() {
return buildingName;
}

public void setBuildingName(String buildingName) {
this.buildingName = buildingName;
}

@Column
public String getTown() {
return town;
}

public void setTown(String town) {
this.town = town;
}

@Column
public String getPostCode() {
return postCode;
}

public void setPostCode(String postCode) {
this.postCode = postCode;
}

@ManyToMany(mappedBy = "addresses")
public Set<Person> getPersons() {
return persons;
}

public void setPersons(Set<Person> persons) {
this.persons = persons;
31

77
78
79
}

}
8. Create Database
Now go to any MySQL query tool (Preferably SQLYog)
Create a database called hibernatetutorial with utf8 encoding:
1 CREATE DATABASE hibernatetutorial CHARACTER SET = utf8 COLLATE = utf8_bin;
Create person, address and person_address tables as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
create table address (
address_id bigint not null auto_increment,
buildingName varchar(255),
postCode varchar(255),
town varchar(255),
primary key (address_id)
);

create table person (
person_id bigint not null auto_increment,
firstName varchar(255),
lastName varchar(255),
primary key (person_id)
);

create table person_address (
person_id bigint not null,
address_id bigint not null,
primary key (person_id, address_id)
);
Heres the table relationship diagram:

32

As you can see, there is a one-to-many relationship between person and person_address, one-to-
many relationship between address and person_address and as a result of that, many-to-many
relationship between person and address tables.
9. Writing Test Program
Create a HibernateUtil class to read XML database configuration we did earlier and create a
Configuration object to obtain a SessionFactory object. Please make sure that hibernate.cfg.xml
file is on the classpath. Following is code of the HibernateUtil.java class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.codejava.hibernate.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {

private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
return configuration.buildSessionFactory(serviceRegistry);
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Ideally, its a good practice to create one SessionFactory object per data store at global
application level scope. Hence here we are creating just one static SessionFactory object when
the class is first loaded and then we access the same via getSessionFactory() static method. This
is the safest implementation of a singleton object.
33

Now lets create a PersonManager class which creates 2 person and 3 address objects and
persists them to the database. Note that all the addresses have been persisted using Hibernate
cascade functionality. Here is code of the PersonManager.java class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package net.codejava.hibernate.manager;

import net.codejava.hibernate.model.Address;
import net.codejava.hibernate.model.Person;
import net.codejava.hibernate.util.HibernateUtil;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class PersonManager {

public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();

Person steve = new Person("Steve", "Jobs");
Person donald = new Person("Donald", "Trump");

Address valley = new Address("Steve P Jobs", "San Francisco", "11111");
Address newyork = new Address("Trump Tower", "New York", "22222");
Address chicago = new Address("Trump Tower", "Chicago", "33333");

steve.getAddresses().add(valley);
donald.getAddresses().add(newyork);
donald.getAddresses().add(chicago);

System.out.println("Creating Person: " + steve.getFirstName());
session.persist(steve);
System.out.println("Creating Person: " + donald.getFirstName());
session.persist(donald);

session.getTransaction().commit();
session.close();
}

}
Just right click in the editor window and run the project as Java application. You should see
following output in the console
1 Creating Person: Steve
34

2 Creating Person: Donald
Heres the final database presentation you should see:

Person table

Address table

Person_Address table
Above you can see that in person table, persons Steve and Donald have been saved with auto
generated ids 1 and 2 respectively. In address table, addresses San Francisco, Chicago and New
York have been saved with auto generated ids 1, 2 and 3 respectively. Also in person_address
table person_id 1 is associated with address_id 1 and person_id 2 is associated with address_ids
2 and 3 respectively.
This tutorial shows how easily you can configure session factory connection details using XML
and entities using annotation configuration respectively in Hibernate and access the database. By
using XML, database connection properties can be easily changed without changing the Java
source files which is an added advantage. By using annotations, Java entity classes are more
expressive and you dont have to refer to another XML file for figuring out the Hibernate-
Database mapping.
Above shown code snippets can be downloaded as a full Eclipse project along with the
accompanying jar files from the attachment section.
Building Hibernate SessionFactory from Service Registry
In Hibernate, it was often to build a SessionFactory and pull out a Session as follows:
35

1
2
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
However, since Hibernate 4.x, this approach is deprecated. According to Hibernate 4.0 API
docs, the Configuration class buildSessionFactory() method is deprecated and it recommends
developers to use the buildSessionFactory(ServiceRegistry) instead. Here is the new
recommended code snippet that builds the SessionFactory based on a ServiceRegistry and
obtains the Session:
1
2
3
4
5
6
7
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

Session session = sessionFactory.openSession();
The Configuration class configure() method loads mappings and properties from the convention
resource file hibernate.cfg.xml which should be present in the classpath. Its also very common
to create a separate utility class for building the SessionFactory as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package net.codejava.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {

private static SessionFactory sessionFactory;

public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}

return sessionFactory;
}

}
36

NOTE: As of 2014, the above code is deprecated. Heres new version of the HibernateUtil class
that is up-to-date:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package net.codejava.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
private static SessionFactory sessionFactory;

public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry
= new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();

// builds a session factory from the service registry
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}

return sessionFactory;
}
}
Heres an example of using this utility class in a Hibernate application:
1
2
3
4
5
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(myObject);

Hibernate One-to-One With Foreign Key XML Mapping Example
This Hibernate tutorial helps you learn how to implement a one-to-one association using XML
mapping approach, by developing a sample Hibernate application that manages the following
entity relationship:
37


This relationship is supposing a book has only one author. It is called unidirectional one-to-one
association on a foreign key in which the parent table (book) refers to child table (author) by a
foreign key (author_id). The navigation is one-way from the book to the author: its possible to
know author of a book, but not vice-versa. Note that this relationship is for the purpose of demo
only.
The sample application in this tutorial is developed and tested in the following environment:
o Hibernate 4.2.2.Final
o JDK 7
o Eclipse IDE 4.2 (Juno)
o MySQL Community Server 5.5.23
o MySQL Connector Java driver 5.1.25
Lets follow the steps described below.
Table of content:
1. Creating database and tables
2. Creating Eclipse project
3. Creating Model Classes
4. Creating Hibernate mapping files
5. Creating Hibernate Configuration File
6. Creating a test program
1. Creating database and tables
First, we need to create a sample database with two tables: book and author. Execute the
following SQL script in MySQL Workbenchs SQL Editor:
1
2
3
4
5
6
create database booksdb;
use booksdb;

CREATE TABLE `author` (
`author_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
38

7
8
9
10
11
12
13
14
15
16
17
18
19
20
`email` varchar(45) NOT NULL,
PRIMARY KEY (`author_id`)
);

CREATE TABLE `book` (
`book_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(128) NOT NULL,
`description` varchar(512) NOT NULL,
`published` date NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`book_id`),
KEY `author_fk` (`author_id`),
CONSTRAINT `author_fk` FOREIGN KEY (`author_id`) REFERENCES `author`
(`author_id`)
);
In case you are using MySQL Command Line Client program, run the following command:
source Path\To\The\Script\File\MySQLscript.sql
The MySQLscript.sql file can be found in the attached project or can be created from the above
script. You would end up with a database called booksdb and two tables author and book as
shown below:
2. Creating Eclipse project
Create a standard Java project in Eclipse IDE with the following structure:
39


The project consists of the following files:
o Model classes: Author.java and Book.java
o Hibernate XML mapping files: Author.hbm.xml and Book.hbm.xml
o Hibernate XML configuration file: hibernate.cfg.xml
o Test program: BooksManager.java
o Hibernate required JAR libraries and MySQL Connector Java driver:
hibernate-core-4.2.2.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
mysql-connector-java-5.1.25-bin.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jboss-logging-3.1.0.GA.jar
antlr-2.7.7.jar
dom4j-1.6.1.jar
javassist-3.15.0-GA.jar
o SQL script file for MySQL: MySQLscript.sql
The Hibernate required libraries can be found under hibernate-release-VERSI ON\lib\required
directory from Hibernate distribution archive.
3. Creating Model Classes
40

We need to create two Java model classes according to two database tables: Author.java and
Book.java. These are standard JavaBean-style classes.
File net\codejava\hibernate\Author.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package net.codejava.hibernate;

public class Author {
private long id;
private String name;
private String email;

public Author() {
}

public Author(String name, String email) {
this.name = name;
this.email = email;
}

public long getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}


}
41

File net\codejava\hibernate\Book.java:
package net.codejava.hibernate;

import java.util.Date;

public class Book {
private long id;
private String title;
private String description;
private Date publishedDate;
private Author author;
public Book() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public Date getPublishedDate() {
return publishedDate;
}

public void setPublishedDate(Date publishedDate) {
this.publishedDate = publishedDate;
}

public Author getAuthor() {
42

return author;
}

public void setAuthor(Author author) {
this.author = author;
}

}
Note that the Book class has a property of type Author which denotes a has-a relationship in
terms of object oriented programming.
4. Creating Hibernate mapping files
We need to tell Hibernate what are our model classes and how they associate with database
tables by creating XML mapping files who names in the format of ModelClassName.hbm.xml.
Create two XML files Author.hbm.xml and Book.hbm.xml with the following content:
File net\codejava\hibernate\Author.hbm.xml:
<?xml version="1.0"?>
<!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="Author" table="AUTHOR">
<id name="id" column="AUTHOR_ID">
<generator class="native"/>
</id>
<property name="name" column="NAME" />
<property name="email" column="EMAIL" />
</class>
</hibernate-mapping>
File net\codejava\hibernate\Book.hbm.xml:
<?xml version="1.0"?>
<!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="Book" table="BOOK">
<id name="id" column="BOOK_ID">
<generator class="native" />
</id>
<property name="title" type="string" column="TITLE" />
43

<property name="description" type="string" column="DESCRIPTION" />
<property name="publishedDate" type="date" column="PUBLISHED" />

<many-to-one name="Author" class="net.codejava.hibernate.Author"
column="author_id" unique="true" not-null="true"
cascade="all" />

</class>
</hibernate-mapping>
Pay attention to the <many-to-one> element used in the Book.hbm.xml file. It is used to create
the one-to-one relationship between the Book and Author entities. The attributes unique=true
and not-null=true enforce this relationship.
5. Creating Hibernate Configuration File
To tell Hibernate to use which database type, connection details and the above mapping files, we
need to create a hibernate.cfg.xml file:
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/booksdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping resource="net/codejava/hibernate/Book.hbm.xml"/>
<mapping resource="net/codejava/hibernate/Author.hbm.xml"/>

</session-factory>
</hibernate-configuration>
This configuration specifies database driver type is MySQL and connection URL points to the
database booksdb. You may change the database username and password according to yours.
And finally we tell Hibernate to load two mapping files Author.hbm.xml and Book.hbm.xml.
6. Creating a test program
44

So far we have created all the nuts and bolts of configuration stuff. Its time to write a simple test
program that persists a Book entity to the database, gets it back and prints out the details. Heres
code of the BooksManager class:
package net.codejava.hibernate;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
* This program demonstrates using Hibernate framework to manage
* a one-to-one entity relationship.
* @author www.codejava.net
*
*/
public class BooksManager {

public static void main(String[] args) {

// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

// creates a Book entity
Book newBook = new Book();
newBook.setTitle("Effective Java");
newBook.setDescription("Best practices for Java programming");
newBook.setPublishedDate(new Date());
newBook.setAuthor(new Author("Joshua Bloch", "joshua.bloch@gmail.com"));

// persists the book entity
Long bookId = (Long) session.save(newBook);
45


// gets the book entity back
Book book = (Book) session.get(Book.class, bookId);
System.out.println("Title: " + book.getTitle());
System.out.println("Description: " + book.getTitle());

Author author = book.getAuthor();
System.out.println("Author's name: " + author.getName());
System.out.println("Author's email: " + author.getEmail());

session.getTransaction().commit();
session.close();
}
}
Output of the program:
Hibernate: insert into AUTHOR (NAME, EMAIL) values (?, ?)
Hibernate: insert into BOOK (TITLE, DESCRIPTION, PUBLISHED, author_id) values
(?, ?, ?, ?)
Title: Effective Java
Description: Effective Java
Author's name: Joshua Bloch
Author's email: joshua.bloch@gmail.com
Result in the Book table:

Result in the Author table:





46

Hibernate Many-to-Many XML Mapping Example
This Hibernate tutorial is going to teach you how to model a bidirectional many-to-many
association using XML schema. The following entity relationship diagram illustrates a typical
many-to-many association:

A many-to-many association
We are going to develop a sample Hibernate application that manages the above association in
which a user may belong to many groups, and a group may contain many users. The
UsersGroups is the join table between the groups and users tables.
The following pieces of software/library are used in this tutorial:
o Hibernate 4.2.2.Final
o JDK 7
o Eclipse IDE 4.2 (Juno)
o MySQL Community Server 5.5.23
o MySQL Connector Java driver 5.1.25
Table of content:
1. Creating Database and Tables
2. Setting up an Eclipse project
3. Coding Hibernate Model Classes
4. Writing Hibernate Mapping Files
5. Writing Hibernate Configuration File
6. Coding a Test Program
1. Creating Database and Tables
We will create a MySQL database called usersdb and three tables: users, groups and
UsersGroups (join table). If you are using MySQL Workbench program, executing the following
script in its SQL Editor:
create database usersdb;

47

use usersdb;

CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
`email` varchar(45) NOT NULL,
PRIMARY KEY (`user_id`)
);

CREATE TABLE `groups` (
`group_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`group_id`)
);

CREATE TABLE `UsersGroups` (
`user_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`group_id`),
KEY `fk_user` (`user_id`),
KEY `fk_group` (`group_id`),
CONSTRAINT `fk_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`),
CONSTRAINT `fk_group` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`)
);
Or type the following command in case you are using MySQL Command Line Client program:
source Path\To\The\Script\File\MySQLscript.sql
In which the MySQLscript.sql file can be created from the above script or picked up from the
attached project. The newly created database would have the following structure:

48

2. Setting up an Eclipse project
In Eclipse IDE, create a standard Java project named HibernateMany2ManyXMLExample
with the following structure:

As we can see, the project contains the following files:
o Model classes: Group.java and User.java
o Hibernate XML mapping files: Group.hbm.xml and User.hbm.xml
o Hibernate XML configuration file: hibernate.cfg.xml
o Test program: UsersManager.java
o Hibernate required JAR libraries and MySQL Connector Java driver:
hibernate-core-4.2.2.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
mysql-connector-java-5.1.25-bin.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jboss-logging-3.1.0.GA.jar
antlr-2.7.7.jar
dom4j-1.6.1.jar
javassist-3.15.0-GA.jar
o MySQL script file: MySQLscript.sql
The Hibernate and MySQL Connector/J jar files can be found from their distribution archives.
49

3. Coding Hibernate Model Classes
Create two JavaBean-style model classes corresponding to the groups and users tables as
follows:
File net\codejava\hibernate\Group.java:
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

public class Group {
private long id;
private String name;

private Set<User> users = new HashSet<User>();

public Group(String name) {
this.name = name;
}

public void addUser(User user) {
this.users.add(user);
}

// setters and getters
}
File net\codejava\hibernate\User.java:
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

public class User {
private long id;
private String username;
private String password;
private String email;

private Set<Group> groups = new HashSet<Group>();

public User(String username, String password, String email) {
this.username = username;
50

this.password = password;
this.email = email;
}

public void addGroup(Group group) {
this.groups.add(group);
}

// setters and getters
}
NOTES: For a bidirectional many-to-many association, we should specify a collection of
another side from each side (using java.util.Set implementation in this tutorial). For example:
o A Group has a set of Users.
o A User has a set of Groups.
And note that the methods addUser(User) and addGroup(Group) were added to make adding
items to the collection easily.
4. Writing Hibernate Mapping Files
To map the above model classes with the database tables, create two Hibernate mapping files
Group.hbm.xml and User.hbm.xml as follows:
File net\codejava\hibernate\Group.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="Group" table="GROUPS">
<id name="id" column="GROUP_ID">
<generator class="native"/>
</id>
<property name="name" column="NAME" />

<set name="users" table="UsersGroups" cascade="save-update">
<key column="GROUP_ID"/>
<many-to-many column="USER_ID" class="User" />
</set>
</class>
</hibernate-mapping>

51

File net\codejava\hibernate\User.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="User" table="USERS">
<id name="id" column="USER_ID">
<generator class="native"/>
</id>
<property name="username" column="USERNAME" />
<property name="password" column="PASSWORD" />
<property name="email" column="EMAIL" />

<set name="groups" table="UsersGroups" inverse="true">
<key column="USER_ID"/>
<many-to-many column="GROUP_ID" class="Group" />
</set>
</class>
</hibernate-mapping>
NOTES:
o We have to specify name of the join table (UsersGroups) in the <set> element.
o The attribute inverse=true can be placed on either side to specify which is
owner of the relationship. In the mapping above, the relationship owner is the
Group (because inverse=true is set on the User side).
o The attribute cascade=save-update on the Group side tells Hibernate to
update the children (users) when the parent (group) is saved or updated.
o We dont have to create model class/mapping file for the join table.
5. Writing Hibernate Configuration File
We need to tell Hibernate which database type and mapping files needs to be used, so create the
Hibernate configuration file (hibernate.cfg.xml) with the following content:
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/usersdb</property>
52

<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping resource="net/codejava/hibernate/User.hbm.xml"/>
<mapping resource="net/codejava/hibernate/Group.hbm.xml"/>

</session-factory>
</hibernate-configuration>
NOTES: Change the username and password according to your MySQL account.
6. Coding a Test Program
Following is a test program that persists the following entities and relationship:
o Administrator Group > User 1
o Administrator Group > User 2
o Guest Group > User 1
Here is the source code:
package net.codejava.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
* A program that demonstrates using Hibernate framework to manage
* a bidirectional many-to-many association in relational database.
* @author www.codejava.net
*
*/
public class UsersManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

53

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration
.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Group groupAdmin = new Group("Administrator Group");
Group groupGuest = new Group("Guest Group");

User user1 = new User("Tom", "tomcat", "tom@codejava.net");
User user2 = new User("Mary", "mary", "mary@codejava.net");

groupAdmin.addUser(user1);
groupAdmin.addUser(user2);

groupGuest.addUser(user1);

user1.addGroup(groupAdmin);
user2.addGroup(groupAdmin);
user1.addGroup(groupGuest);

session.save(groupAdmin);
session.save(groupGuest);

session.getTransaction().commit();
session.close();
}

}
Output of the program:
Hibernate: insert into GROUPS (NAME) values (?)
Hibernate: insert into USERS (USERNAME, PASSWORD, EMAIL) values (?, ?, ?)
Hibernate: insert into USERS (USERNAME, PASSWORD, EMAIL) values (?, ?, ?)
Hibernate: insert into GROUPS (NAME) values (?)
Hibernate: insert into UsersGroups (GROUP_ID, USER_ID) values (?, ?)
Hibernate: insert into UsersGroups (GROUP_ID, USER_ID) values (?, ?)
Hibernate: insert into UsersGroups (GROUP_ID, USER_ID) values (?, ?)
Result in the groups table:
54


Result in the users table:

Result in the UsersGroups table:



Hibernate One-to-One Association on Primary Key Annotations Example
In this Hibernate tutorial series, we are going to show you how to implement a bidirectional one-
to-one association using JPA and Hibernate annotations. The annotations approach is preferred
as an alternative to XML descriptor which is described in the tutorial Hibernate One-to-One
With Primary Key XML Mapping Example. Lets recall about the bidirectional one-to-one
association by looking at the following entity relationship diagram:

55

As we can see, these two tables share a same primary key (product_id) so that its possible to
navigate to a corresponding product_detail from a product and vice-versa, thus this is called
bidirectional (two-ways) association on primary key.
In this tutorial, we will be developing a sample Hibernate program to manage the above product
- product_detail association using the following pieces of software:
Hibernate 4.2.7.SP1
JDK 7
Eclipse IDE 4.3 (Kepler)
Maven 3
MySQL Community Server 5.5.23
MySQL Connector Java driver 5.1.26
The software versions here are the latest as of this writing, but using similar versions is also
possible. Here are the steps we should follow:
Table of content:
1. Creating Database and Tables
2. Creating Maven-Eclipse Project
3. Coding Model Classes with Annotations
4. Writing Hibernate Configuration File
5. Writing a Test Program
1. Creating Database and Tables
Lets create a database called productsdb containing two tables product and product_detail by
executing the following MySQL script:
create database productsdb;
use productsdb;

CREATE TABLE `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`description` varchar(512) NOT NULL,
`price` float NOT NULL,
PRIMARY KEY (`product_id`)
);

CREATE TABLE `product_detail` (
`product_id` int(11) NOT NULL,
`part_number` varchar(45) NOT NULL,
`dimension` varchar(45) NOT NULL,
`weight` float NOT NULL,
56

`manufacturer` varchar(45) NOT NULL,
`origin` varchar(45) NOT NULL,
PRIMARY KEY (`product_id`)
);
We would have the following database structure:

2. Creating Maven-Eclipse Project
Eclipse Kepler has Maven integration by default, so creating a Maven project is quick and easy.
Lets create a Maven project with the following structure:

The project HibernateOne2OnePrimaryKeyAnnotationsExample consists of the following
files:
57

Model classes: Product.java and ProductDetail.java
Hibernate XML configuration file: hibernate.cfg.xml
Test program: ProductsManager.java
Maven project: pom.xml
We specify two primary dependencies of hibernate-core and mysql-connector-java in the
pom.xml file as follows:
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.codejava.hibernate</groupId>
<artifactId>HibernateOne2OnePrimaryKeyAnnotationsExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.7.SP1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>
</project>
The other related dependencies will be resolved automatically by Maven.
3. Coding Model Classes with Annotations
Create two model classes called Product.java and ProductDetail.java with the following source
code:
File net\codejava\hibernate\Product.java:
package net.codejava.hibernate;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
58

import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "PRODUCT")
public class Product {
private long productId;
private String name;
private String description;
private float price;
private ProductDetail productDetail;

public Product() {
}

@Id
@GeneratedValue
@Column(name = "PRODUCT_ID")
public long getProductId() {
return productId;
}

@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public ProductDetail getProductDetail() {
return productDetail;
}

// other getters and setters
}
File net\codejava\hibernate\ProductDetail.java:
package net.codejava.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

59

@Entity
@Table(name = "PRODUCT_DETAIL")
public class ProductDetail {
private long productId;
private String partNumber;
private String dimension;
private float weight;
private String manufacturer;
private String origin;
private Product product;

public ProductDetail() {
}

@Id
@GeneratedValue(generator = "foreigngen")
@GenericGenerator(strategy = "foreign", name="foreigngen",
parameters = @Parameter(name = "property", value="product"))
@Column(name = "PRODUCT_ID")
public long getProductId() {
return productId;
}


@Column(name = "PART_NUMBER")
public String getPartNumber() {
return partNumber;
}

@OneToOne(mappedBy = "productDetail")
public Product getProduct() {
return product;
}

// other getters and setters
}
Here, we use several annotations as you notice: The @Entity, @Table and @Column
annotations are straightforward to understand. The others need some further explanations:
@Id and @GeneratedValue: are used in conjunction to map a field as the primary key
of the table. Typically, the primary keys values are auto-generated.
On the Product side, we use the @OneToOne and @PrimaryKeyJoinColumn
annotations to tell Hibernate creates a one-to-one association with the ProductDetail and
the join column is the primary key column.
60

On the ProductDetail side, we need to use the @GenericGenerator to specify a foreign
key strategy in order to generate values for the product_id column as a foreign key. And
the @OneToOne annotation tells Hibernate that the product field is a one-to-one
association which is mapped by this productDetail.
4. Writing Hibernate Configuration File
We need to write XML descriptor in the hibernate.cfg.xml file to tell Hibernate which database
to connect:
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/productsdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping class="net.codejava.hibernate.Product"/>
<mapping class="net.codejava.hibernate.ProductDetail"/>

</session-factory>
</hibernate-configuration>

5. Writing a Test Program
Write code for the test program (ProductsManager.java) as follows:
1
2
3
4
5
6
7
8
9
10
package net.codejava.hibernate;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

61

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* This program demonstrates using Hibernate framework to manage a
* bidirectional one-to-one association on a primary key using
* annotations.
* @author www.codejava.net
*
*/
public class ProductsManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

// creates a new product
Product product = new Product();
product.setName("Civic");
product.setDescription("Comfortable, fuel-saving car");
product.setPrice(20000);

// creates product detail
ProductDetail detail = new ProductDetail();
detail.setPartNumber("ABCDEFGHIJKL");
detail.setDimension("2,5m x 1,4m x 1,2m");
detail.setWeight(1000);
detail.setManufacturer("Honda Automobile");
detail.setOrigin("Japan");

// sets the bi-directional association
product.setProductDetail(detail);
detail.setProduct(product);

// persists the product
session.save(product);

// queries all products
List<Product> listProducts = session.createQuery("from Product").list();
62

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
for (Product aProd : listProducts) {
String info = "Product: " + aProd.getName() + "\n";
info += "\tDescription: " + aProd.getDescription() + "\n";
info += "\tPrice: $" + aProd.getPrice() + "\n";

ProductDetail aDetail = aProd.getProductDetail();
info += "\tPart number: " + aDetail.getPartNumber() + "\n";
info += "\tDimension: " + aDetail.getDimension() + "\n";
info += "\tWeight: " + aDetail.getWeight() + "\n";
info += "\tManufacturer: " + aDetail.getManufacturer() + "\n";
info += "\tOrigin: " + aDetail.getOrigin() + "\n";

System.out.println(info);
}

session.getTransaction().commit();
session.close();
}

}
Output of the program:
1
2
3
4
5
6
7
8
9
10
11
Hibernate: insert into PRODUCT (description, name, price) values (?, ?, ?)
Hibernate: insert into PRODUCT_DETAIL (dimension,...) values (?, ?, ?, ?, ?, ?)
Hibernate: select product0_.PRODUCT_ID ... from PRODUCT product0_
Product: Civic
Description: Comfortable, fuel-saving car
Price: $20000.0
Part number: ABCDEFGHIJKL
Dimension: 2,5m x 1,4m x 1,2m
Weight: 1000.0
Manufacturer: Honda Automobile
Origin: Japan
Result in the product table:

Result in the product_detail table:
63

















Hibernate One-to-Many XML Mapping Example
In this tutorial we are going to understand how to use XML to map a one-to-many association
between Java objects and database tables using Hibernate framework. We will create a sample
Hibernate-based application to manage the following entity relationship:
64


In this relationship, a category can contain one or many products.
The following pieces of software/library are used for this tutorials sample project:
o Hibernate 4.2.2.Final
o JDK 7
o Eclipse IDE 4.2 (Juno)
o MySQL Community Server 5.5.23
o MySQL Connector Java driver 5.1.25
You can click on a link to download the appropriate software/library.
Table of content:
1. Creating sample database and tables
2. Setting up a project in Eclipse
3. Coding Hibernate Model Classes
4. Creating Hibernate Mapping Files
5. Writing Hibernate Configuration File
6. Coding a Test Program
1. Creating sample database and tables
Execute the following script in MySQL Workbenchs SQL Editor to create a database called
stockdb with two tables named category and product:
create database stockdb;
use stockdb;

CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`)
);

65

CREATE TABLE `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`description` varchar(512) NOT NULL,
`price` float NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`product_id`),
KEY `fk_category` (`category_id`),
CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category`
(`category_id`)
);
Or type the following command in MySQL Command Line Client:
source Path\To\The\Script\File\MySQLscript.sql
The MySQLscript.sql file can be located in the attached project or created from the above script.
The newly created database would have the following structure:

2. Setting up a project in Eclipse
Use Eclipse IDE to create a project called HibernateOne2ManyXMLExample with the following
structure:
66


This project consists of the following files:
o Model classes: Category.java and Product.java
o Hibernate XML mapping files: Category.hbm.xml and Product.hbm.xml
o Hibernate XML configuration file: hibernate.cfg.xml
o Test program: StockManager.java
o Hibernate required JAR libraries and MySQL Connector Java driver:
hibernate-core-4.2.2.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
mysql-connector-java-5.1.25-bin.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jboss-logging-3.1.0.GA.jar
antlr-2.7.7.jar
dom4j-1.6.1.jar
javassist-3.15.0-GA.jar
o MySQL script file: MySQLscript.sql
The Hibernate jar files above can be found under hibernate-release-VERSI ON\lib\required
directory from Hibernate distribution archive.

67

3. Coding Hibernate Model Classes
Create two JavaBean-style classes Category.java and Product.java to model the two tables
category and product, respectively.
File net\codejava\hibernate\Category.java:
package net.codejava.hibernate;

import java.util.Set;

public class Category {

private long id;
private String name;

private Set<Product> products;

public Category() {
}

public Category(String name) {
this.name = name;
}

// getters and setters...

}
File net\codejava\hibernate\Product.java:
package net.codejava.hibernate;

public class Product {
private long id;
private String name;
private String description;
private float price;
private Category category;

public Product() {
}

public Product(String name, String description, float price,
Category category) {
this.name = name;
68

this.description = description;
this.price = price;
this.category = category;
}

// getters and setters...

}
NOTES: To model the one-to-many association, we put cross-references in both side:
A Category contains a set of Products:
1 private Set<Product> products;
A Product links back to its category:
1 private Category category;
4. Creating Hibernate Mapping Files
Create two XML files Category.hbm.xml and Product.hbm.xml to tell Hibernate how to map the
JavaBean classes above with the database tables.
File net\codejava\hibernate\Category.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="Category" table="CATEGORY">
<id name="id" column="CATEGORY_ID">
<generator class="native"/>
</id>
<property name="name" column="NAME" />

<set name="products" inverse="true" cascade="all">
<key column="CATEGORY_ID" not-null="true" />
<one-to-many class="Product"/>
</set>
</class>
</hibernate-mapping>
File net\codejava\hibernate\Product.hbm.xml:
69

<?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="Product" table="PRODUCT">
<id name="id" column="PRODUCT_ID">
<generator class="native"/>
</id>
<property name="name" column="NAME" />
<property name="description" column="DESCRIPTION" />
<property name="price" column="PRICE" type="float" />

<many-to-one name="category" class="Category"
column="CATEGORY_ID" not-null="true"/>
</class>
</hibernate-mapping>
NOTES: Pay attention to the attribute inverse=true of the <set> element in the
Category.hbm.xml file. That means this side (Category) is not the relationship owner. Instead, it
is the reverse side (Product) is the relationship owner. Because the product table has a foreign
key that refers to the category table, it is the owner of this one-to-many relationship. So keep in
mind that using inverse=true is mandatory in this case.
5. Writing Hibernate Configuration File
Create the Hibernate configuration file (hibernate.cfg.xml) to specify database type, connection
details and the mapping files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/stockdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping resource="net/codejava/hibernate/Category.hbm.xml"/>
<mapping resource="net/codejava/hibernate/Product.hbm.xml"/>

70

18
19
</session-factory>
</hibernate-configuration>
NOTES: Update the database username and password corresponding to your database settings.
6. Coding a Test Program
Following is code of the test program that persists some sample data:
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
*
* This program demonstrates using Hibernate framework to manage a
* bidirectional one-to-many association.
* @author www.codejava.net
*
*/
public class StockManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Category category = new Category("Computer");

Product pc = new Product("DELL PC", "Quad-core PC", 1200, category);
71


Product laptop = new Product("MacBook", "Apple High-end laptop", 2100, category);

Product phone = new Product("iPhone 5", "Apple Best-selling smartphone", 499, category);

Product tablet = new Product("iPad 3", "Apple Best-selling tablet", 1099, category);

Set<Product> products = new HashSet<Product>();
products.add(pc);
products.add(laptop);
products.add(phone);
products.add(tablet);

category.setProducts(products);

session.save(category);

session.getTransaction().commit();
session.close();
}
}
Output of the program:
Hibernate: insert into CATEGORY (NAME) values (?)
Hibernate: insert into PRODUCT (NAME, DESCRIPTION, PRICE, CATEGORY_ID)
values (?, ?, ?, ?)
Hibernate: insert into PRODUCT (NAME, DESCRIPTION, PRICE, CATEGORY_ID)
values (?, ?, ?, ?)
Hibernate: insert into PRODUCT (NAME, DESCRIPTION, PRICE, CATEGORY_ID)
values (?, ?, ?, ?)
Hibernate: insert into PRODUCT (NAME, DESCRIPTION, PRICE, CATEGORY_ID)
values (?, ?, ?, ?)
Result in the category table:

Result in the product table:
72


Hibernate One-to-Many Association on Join Table Annotations Example
Perhaps one-to-many is one of the most commonly used associations in Object/Relational
Mapping. The best practice is to use a separate join table for a one-to-many association to gain
flexibility and scalability. Therefore, this Hibernate tutorial is dedicated for mapping such kind
of association using JPA annotations, with a sample program will be developed in Eclipse and
Maven, and the database is MySQL. This is an alternative approach to the XML descriptor as
described in the tutorial: Hibernate One-to-Many Using Join Table XML Mapping Example.
A typical one-to-many association on join table is illustrated in the following diagram:

Here, a join table (category_article) is created to make the one-to-many association between the
category and article tables.
To develop the sample program, we use the following pieces of software programs and libraries
(you can use similar versions):
Hibernate 4.2.7.SP1
JDK 7
Eclipse IDE 4.3 (Kepler)
Maven 3
MySQL Community Server 5.5.23
MySQL Connector Java driver 5.1.26
Table of content:
1. Creating Database and Tables
2. Creating Maven-Eclipse Project
73

3. Using Annotations for One-to-Many Association on Join Table
4. Writing Hibernate Configuration File
5. Writing a Test Program
1. Creating Database and Tables
The following MySQL script is used to create a database called newsdb with three tables:
category, article and category_article (join table):
CREATE DATABASE `newsdb`;

use newsdb;

CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`)
);


CREATE TABLE `article` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(70) NOT NULL,
`description` varchar(250) NOT NULL,
`keywords` varchar(150) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`article_id`)
);

CREATE TABLE `category_article` (
`category_id` int(11) NOT NULL,
`article_id` int(11) NOT NULL,
PRIMARY KEY (`category_id`,`article_id`),
UNIQUE KEY `article_id_UNIQUE` (`article_id`),
KEY `fk_category` (`category_id`),
KEY `fk_article` (`article_id`),
CONSTRAINT `fk_article` FOREIGN KEY (`article_id`) REFERENCES `article`
(`article_id`),
CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category`
(`category_id`)
);
Notice that the column article_id of the join table is set with unique key constraint to enforce the
one-to-many association, meaning that there is no one article belongs to more than one category.
Thus we have the structure of the newsdb database as follows:
74


Recommended Book: Hibernate Made Easy: Simplified Data Persistence with Hibernate
and JPA (Java Persistence API) Annotations

2. Creating Maven-Eclipse Project
In Eclipse IDE, create a Maven project named
HibernateOne2ManyJoinTableAnnotationsExample with the following structure:

75

This project consists of the following files:
Model classes: Category.java and Article.java
Hibernate XML configuration file: hibernate.cfg.xml
Test program: ArticlesManager.java
Maven project: pom.xml
And update the pom.xml file for the latest Hibernate release and MySQL Connector/J library as
follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.codejava.hibernate</groupId>
<artifactId>HibernateOne2ManyJoinTableAnnotationsExample</artifactId>
<version>1.0</version>
<description>A sample Hibernate application that maps a one-to-many association
on join table using annotations</description>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.7.SP1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>
</project>
All other dependencies will be resolved automatically by Maven.

3. Using Annotations for One-to-Many Association on Join Table
To represent the one-to-many association in the object model, lets create two classes called
Category.java and Article.java as follows:
File net\codejava\hibernate\Category.java:
1
2
package net.codejava.hibernate;

76

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "CATEGORY")
public class Category {

private long id;
private String name;

private Set<Article> articles;

public Category() {
}

public Category(String name) {
this.name = name;
}

@Id
@GeneratedValue
@Column(name = "CATEGORY_ID")
public long getId() {
return id;
}

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "CATEGORY_ARTICLE",
joinColumns = @JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = @JoinColumn(name = "ARTICLE_ID")
)

// other getters and setters...

}
77

File net\codejava\hibernate\Article.java:
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 = "ARTICLE")
public class Article {
private long id;
private String title;
private String description;
private String keywords;
private String content;

public Article() {
}

public Article(String title, String description, String keywords,
String content) {
this.title = title;
this.description = description;
this.keywords = keywords;
this.content = content;
}

@Id
@GeneratedValue
@Column(name = "ARTICLE_ID")
public long getId() {
return id;
}

// other getters and setters...
}
We can see that a Category has a set of Articles, but an Article doesnt have any back reference
to the Category, thus this association is unidirectional.
To map the one-to-many association on join table, these JPA annotations are used:
@OneToMany, @JoinTable and @JoinColumn, besides the basic annotations (@Entity,
@Column, @Id, etc) . Lets look at the code in the Category side closely:
78

private Set<Article> articles;

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "CATEGORY_ARTICLE",
joinColumns = @JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = @JoinColumn(name = "ARTICLE_ID")
)
public Set<Article> getArticles() {
return articles;
}
Here, we use the @JoinTable annotation to specify the details of the join table (table name and
two join columns - using the @JoinColumn annotation); and we set the cascade attribute of the
@OneToMany annotation so that Hibernate will update the associated articles when the
category is updated.
And note that we dont have to use any special annotations for the Article side, as this
association is unidirectional; and there is no need to create a mapping class for the join table.
4. Writing Hibernate Configuration File
To tell Hibernate which database to connect and what the mapping classes are, create the
hibernate.cfg.xml file under the classpath with the following content:
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/newsdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping class="net.codejava.hibernate.Category"/>
<mapping class="net.codejava.hibernate.Article"/>

</session-factory>
</hibernate-configuration>

79

5. Writing a Test Program
To test the association mapping we have made so far, lets write a test program that saves some
dummy data with the following code (ArticlesManager.java):
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
* This program demonstrates how to use JPA annotations to map
* a one-to-many association on join table in Hibernate.
* @author www.codejava.net
*
*/
public class ArticlesManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration
.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Category category = new Category("Hibernate Framework");

Article articleOne = new Article("One-to-One Mapping",
"One-to-One XML Mapping Tutorial", "Hibernate,One-to-One",
"Content of One-to-One XML Mapping Tutorial");
Article articleTwo = new Article("One-to-Many Mapping",
"One-to-Many XML Mapping Tutorial", "Hibernate,One-to-Many",
80

"Content of One-to-Many XML Mapping Tutorial");
Article articleThree = new Article("Many-to-Many Mapping",
"Many-to-Many XML Mapping Tutorial", "Hibernate,Many-to-Many",
"Content of Many-to-Many XML Mapping Tutorial");

Set<Article> articles = new HashSet<Article>();
articles.add(articleOne);
articles.add(articleTwo);
articles.add(articleThree);

category.setArticles(articles);

session.save(category);

session.getTransaction().commit();
session.close();
}

}
Output of the program:
1
2
3
4
5
6
7
Hibernate: insert into CATEGORY (name) values (?)
Hibernate: insert into ARTICLE (content, description, keywords, title) values (?, ?, ?, ?)
Hibernate: insert into ARTICLE (content, description, keywords, title) values (?, ?, ?, ?)
Hibernate: insert into ARTICLE (content, description, keywords, title) values (?, ?, ?, ?)
Hibernate: insert into CATEGORY_ARTICLE (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Hibernate: insert into CATEGORY_ARTICLE (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Hibernate: insert into CATEGORY_ARTICLE (CATEGORY_ID, ARTICLE_ID) values (?, ?)
Result in the category table:

Result in the article table:

Result in the join table category_article:
81



Hibernate One-to-One Mapping with Foreign Key Annotations Example
This Hibernate tutorial demonstrates how to use JPA annotations in order to implement a
unidirectional one-to-one association on a foreign key. This is similar to the tutorial Hibernate
One-to-One With Foreign Key XML Mapping Example but using annotations instead of XML
descriptor. The following diagram recalls the one-to-one entity relationship:

A book belongs to only one author, and we can only know the author from the book, not vice-
versa. Thus the association is called unidirectional (one-way).
We are going to develop a sample Hibernate application using the following
technologies/software programs:
Hibernate 4.2.6.Final
JDK 7
Eclipse IDE 4.3 (Kepler)
Maven 3
MySQL Community Server 5.5.23
MySQL Connector Java driver 5.1.26
Note that we use the latest stuffs to date, you can use little bit lower or higher versions. Now,
lets following the steps below:
Table of content:
1. Creating Database and Tables
2. Creating Eclipse Project
3. Coding Model Classes with Annotations
82

4. Writing Hibernate Configuration File
5. Writing a Test Program
1. Creating Database and Tables
Execute the following MySQL script to create the database booksdb with two tables author and
book:
create database booksdb;
use booksdb;

CREATE TABLE `author` (
`author_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`email` varchar(45) NOT NULL,
PRIMARY KEY (`author_id`)
);

CREATE TABLE `book` (
`book_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(128) NOT NULL,
`description` varchar(512) NOT NULL,
`published` date NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`book_id`),
KEY `author_fk` (`author_id`),
CONSTRAINT `author_fk` FOREIGN KEY (`author_id`) REFERENCES `author`
(`author_id`)
);
The database structure looks like this:

83

2. Creating Eclipse Project
Create a Maven project in Eclipse with the following structure:

The project consists of the following files:
Model classes: Author.java and Book.java
Hibernate XML configuration file: hibernate.cfg.xml
Test program: BooksManager.java
Maven project: pom.xml
Heres content of the pom.xml file:
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>HibernateOne2OneAnnnotationsExample</groupId>
<artifactId>HibernateOne2OneAnnnotationsExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Example of a Hibernate one-to-one mapping with
foreign key using annotations</description>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.7.SP1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
84

<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>
</project>
Here, we specify two main dependencies: hibernate-core and mysql-connector-java. Maven
will resolve other related dependencies automatically.
3. Coding Model Classes with Annotations
The followings are code of the two model classes: Author.java and Book.java.
File net\codejava\hibernate\Author.java:
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 = "AUTHOR")
public class Author {
private long id;
private String name;
private String email;

public Author() {
}

public Author(String name, String email) {
this.name = name;
this.email = email;
}

@Id
@Column(name = "AUTHOR_ID")
@GeneratedValue
public long getId() {
return id;
}

public void setId(long id) {
85

this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}
File net\codejava\hibernate\Book.java:
package net.codejava.hibernate;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "BOOK")
public class Book {
private long id;
private String title;
private String description;
private Date publishedDate;

private Author author;
86

public Book() {
}

@Id
@Column(name = "BOOK_ID")
@GeneratedValue
public long getId() {
return id;
}

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

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

@Temporal(TemporalType.DATE)
@Column(name = "PUBLISHED")
public Date getPublishedDate() {
return publishedDate;
}

public void setPublishedDate(Date publishedDate) {
this.publishedDate = publishedDate;
}

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "AUTHOR_ID")
public Author getAuthor() {
return author;
}

87

public void setAuthor(Author author) {
this.author = author;
}
}
As you notice, we use the following JPA annotations:
@Entity: is required for every model class.
@Table: maps the class with the corresponding database table. If omitted, Hibernate will
use the class name.
@Column: maps the field with the corresponding table column. If omitted, Hibernate
will infer the column name and type based on signatures of the getter/setter.
@Id and @GeneratedValue: are used in conjunction for a field that maps to the primary
key. The values for this field are auto generated.
@Temporal: must be used with a java.util.Date field to specify the actual SQL type of
the column.
@OneToOne and @JoinColumn: are used together to specify a one-to-one association
and the join column.
Using annotations is usually preferred over XML descriptor because its simple and
straightforward in the code.
4. Writing Hibernate Configuration File
Write XML configuration for database settings and mapping classes in the hibernate.cfg.xml file
as follows:
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/booksdb</property>
<property name="connection.username">root</property>
<property name="connection.password">P@ssw0rd</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping class="net.codejava.hibernate.Book"/>
<mapping class="net.codejava.hibernate.Author"/>

</session-factory>
</hibernate-configuration>
88

5. Writing a Test Program
Write code for the test program (BooksManager.java) as follows:
package net.codejava.hibernate;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
* This program demonstrates using Hibernate framework to manage
* a one-to-one mapping with foreign key using annotations.
* @author www.codejava.net
*
*/
public class BooksManager {

public static void main(String[] args) {

// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

// creates a Book entity
Book newBook = new Book();
newBook.setTitle("Hibernate Made Easy");
newBook.setDescription("Simplified Data Persistence with Hibernate and JPA");
newBook.setPublishedDate(new Date());

newBook.setAuthor(new Author("Cameron Wallace McKenzie", "Cameron@gmail.com"));

// persists the book entity
89

Long bookId = (Long) session.save(newBook);

// gets the book entity back
Book book = (Book) session.get(Book.class, bookId);
System.out.println("Book's Title: " + book.getTitle());
System.out.println("Book's Description: " + book.getTitle());

Author author = book.getAuthor();
System.out.println("Author's Name: " + author.getName());
System.out.println("Author's Email: " + author.getEmail());

session.getTransaction().commit();
session.close();
}
}
Output of the program:
1
2
3
4
5
Hibernate: insert into AUTHOR (email, name) values (?, ?)
Hibernate: insert into BOOK (AUTHOR_ID, description, PUBLISHED, title) values (?, ?, ?, ?)
Book's Title: Hibernate Made Easy
Book's Description: Hibernate Made Easy
Author's Name: Cameron Wallace McKenzie
Result in the Book table:

Result in the Author table:






90

Hibernate One-to-One With Primary Key XML Mapping Example
This Hibernate tutorial is going to provide an example application that manages a bidirectional
one-to-one association on a primary key which is described by the following entity relationship
diagram:

In this relationship, a product has one and only one detail information. Both the parent table
(product) and child table (product_detail) share a same primary key (product_id). Thus it is
called one-to-one association on a primary key. Lets see how to model this relationship in
Hibernate.
Software programs/libraries used this tutorial:
o Hibernate 4.2.2.Final
o JDK 7
o Eclipse IDE 4.2 (Juno)
o MySQL Community Server 5.5.23
o MySQL Connector Java driver 5.1.25
Table of content:
1. Creating database and tables
2. Setting up Eclipse project
3. Writing Hibernate Model Classes
4. Writing Hibernate Mapping Files
5. Writing Hibernate Configuration File
6. Coding a Test Program
1. Creating database and tables
Lets create a MySQL database called productsdb with two tables product and product_detail.
If you are using MySQL Workbench, execute the following script in a SQL Editor:
create database productsdb;
use productsdb;

91

CREATE TABLE `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
`description` varchar(512) NOT NULL,
`price` float NOT NULL,
PRIMARY KEY (`product_id`)
);

CREATE TABLE `product_detail` (
`product_id` int(11) NOT NULL,
`part_number` varchar(45) NOT NULL,
`dimension` varchar(45) NOT NULL,
`weight` float NOT NULL,
`manufacturer` varchar(45) NOT NULL,
`origin` varchar(45) NOT NULL,
PRIMARY KEY (`product_id`)
);
If you are using MySQL Command Line Client program, type the following command:
source Path\To\The\Script\File\MySQLscript.sql
You can find the MySQLscript.sql file the attached project or save it from the above script. The
following screenshot shows structure of the newly created database:

2. Setting up Eclipse project
Using Eclipse IDE to create a standard Java project that has the following structure:
92


The project consists of the following files:
o Model classes: Product.java and ProductDetail.java
o Hibernate XML mapping files: Product.hbm.xml and ProductDetail.hbm.xml
o Hibernate XML configuration file: hibernate.cfg.xml
o Test program: ProductsManager.java
o Hibernate required JAR libraries and MySQL Connector Java driver:
hibernate-core-4.2.2.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
mysql-connector-java-5.1.25-bin.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jboss-logging-3.1.0.GA.jar
antlr-2.7.7.jar
dom4j-1.6.1.jar
javassist-3.15.0-GA.jar
o MySQL script file: MySQLscript.sql
You can find the above Hibernate libraries under hibernate-release-VERSI ON\lib\required
directory from Hibernate distribution archive.


93

3. Writing Hibernate Model Classes:
To model the tables product and product_detail in Java, create the following two JavaBean-
style classes:
File net\codejava\hibernate\Product.java:
package net.codejava.hibernate;

public class Product {
private long productId;
private String name;
private String description;
private float price;
private ProductDetail productDetail;

public Product() {
}

public ProductDetail getProductDetail() {
return productDetail;
}

public void setProductDetail(ProductDetail detail) {
this.productDetail = detail;
}

// other getters and setters
}
File net\codejava\hibernate\ProductDetail.java:
package net.codejava.hibernate;

public class ProductDetail {
private long productId;
private String partNumber;
private String dimension;
private float weight;
private String manufacturer;
private String origin;
private Product product;

public ProductDetail() {
}

94

public Product getProduct() {
return product;
}

public void setProduct(Product product) {
this.product = product;
}

// other getters and setters
}
NOTES: Both the Product and ProductDetail classes have mutual reference to each other,
through the properties productDetail and product, respectively. This is required for a
bidirectional one-to-one association in which we can navigate the child entity from the parent
and vice-versa, for example:
1
2
3
ProductDetail child = product.getProductDetail();

Product parent = detail.getProduct();
4. Writing Hibernate Mapping Files
Create two XML files corresponding to the two above model classes with the following content:
File net\codejava\hibernate\Product.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="Product" table="PRODUCT">
<id name="productId" column="PRODUCT_ID">
<generator class="native"/>
</id>
<property name="name" column="NAME" />
<property name="description" column="DESCRIPTION" />
<property name="price" column="PRICE" type="float" />

<one-to-one name="productDetail" cascade="all" class="ProductDetail" />
</class>
</hibernate-mapping>
File net\codejava\hibernate\ProductDetail.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
95

<!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="ProductDetail" table="PRODUCT_DETAIL">
<id name="productId" column="PRODUCT_ID">
<generator class="foreign">
<param name="property">product</param>
</generator>
</id>
<property name="partNumber" column="PART_NUMBER" />
<property name="dimension" column="DIMENSION" />
<property name="weight" column="WEIGHT" type="float" />
<property name="manufacturer" column="MANUFACTURER" />
<property name="origin" column="ORIGIN" />

<one-to-one name="product" constrained="true" class="Product" />
</class>
</hibernate-mapping>
NOTES: The <one-to-one> element is used on both sides to enforce their one-to-one
relationship, and the <generator class=foreign> element in the ProductDetail.hbm.xml file
enforces that the product_detail tables primary key is generated based on the product tables
primary key.
5. Writing Hibernate Configuration File
Following is content of the Hibernate configuration file 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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/productsdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping resource="net/codejava/hibernate/Product.hbm.xml"/>
<mapping resource="net/codejava/hibernate/ProductDetail.hbm.xml"/>

96

</session-factory>
</hibernate-configuration>
NOTES: Update the values of the properties connection.username and connection.password
accordingly to your database username and password.
6. Coding a Test Program
Following is code of a demo program that obtains a Hibernate SessionFactory, persists a product
(with detail) and lists all products:
package net.codejava.hibernate;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
* This program demonstrates using Hibernate framework to manage a
* bidirectional one-to-one association on a primary key.
* @author www.codejava.net
*
*/
public class ProductsManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

// creates a new product
Product product = new Product();
product.setName("Civic");
97

product.setDescription("Comfortable, fuel-saving car");
product.setPrice(20000);

// creates product detail
ProductDetail detail = new ProductDetail();
detail.setPartNumber("ABCDEFGHIJKL");
detail.setDimension("2,5m x 1,4m x 1,2m");
detail.setWeight(1000);
detail.setManufacturer("Honda Automobile");
detail.setOrigin("Japan");

// sets the bi-directional association
product.setProductDetail(detail);
detail.setProduct(product);

// persists the product
session.save(product);

// queries all products
List<Product> listProducts = session.createQuery("from Product").list();
for (Product aProd : listProducts) {
String info = "Product: " + aProd.getName() + "\n";
info += "\tDescription: " + aProd.getDescription() + "\n";
info += "\tPrice: $" + aProd.getPrice() + "\n";

ProductDetail aDetail = aProd.getProductDetail();
info += "\tPart number: " + aDetail.getPartNumber() + "\n";
info += "\tDimension: " + aDetail.getDimension() + "\n";
info += "\tWeight: " + aDetail.getWeight() + "\n";
info += "\tManufacturer: " + aDetail.getManufacturer() + "\n";
info += "\tOrigin: " + aDetail.getOrigin() + "\n";

System.out.println(info);
}

session.getTransaction().commit();
session.close();
}

}
Output of the program:
Hibernate: insert into PRODUCT (NAME, DESCRIPTION, PRICE) values (?, ?, ?)
98

Hibernate: insert into PRODUCT_DETAIL (PART_NUMBER, DIMENSION,
WEIGHT, ...
Hibernate: select product0_.PRODUCT_ID as PRODUCT1_0_, product0_.NAME as ...
Product: Civic
Description: Comfortable, fuel-saving car
Price: $20000.0
Part number: ABCDEFGHIJKL
Dimension: 2,5m x 1,4m x 1,2m
Weight: 1000.0
Manufacturer: Honda Automobile
Origin: Japan
Result in the product table:

Result in the product_detail table:











99

Hibernate Many-to-Many Association Annotations Example
In this Hibernate tutorial, we are going to illustrate how to use JPA annotations to map a many-
to-many association (both bidirectional and unidirectional) with a sample program developed
using Eclipse and Maven. MySQL is used as the test database. Using annotations is an alternate
approach (and preferred) to the XML descriptor one: Hibernate Many-to-Many XML Mapping
Example.
Lets recall about a typical many-to-many association:

Here, the multiplicity between the groups and users table is many-to-many, meaning that a
group can have many users and vice-versa, a user can belong to many groups. A join table
(users_groups) is required to connect the both sides.
To develop the sample program, we use the following pieces of software programs and libraries
(you can use similar versions):
Hibernate 4.2.7.SP1
JDK 7
Eclipse IDE 4.3 (Kepler)
Maven 3
MySQL Community Server 5.5.23
MySQL Connector Java driver 5.1.26
Table of content:
1. Creating Database and Tables
2. Creating Maven-Eclipse Project
3. Using Annotations for Many-to-Many Association
4. Writing Hibernate Configuration File
5. Writing a Test Program
1. Creating Database and Tables
The following MySQL script is used to create a database called usersdb with three tables:
groups, users and users_groups (join table):
create database usersdb;
100


use usersdb;

CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
`email` varchar(45) NOT NULL,
PRIMARY KEY (`user_id`)
);

CREATE TABLE `groups` (
`group_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`group_id`)
);

CREATE TABLE `Users_Groups` (
`user_id` int(11) NOT NULL,
`group_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`group_id`),
KEY `fk_user` (`user_id`),
KEY `fk_group` (`group_id`),
CONSTRAINT `fk_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`),
CONSTRAINT `fk_group` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`)
);
The usersdb database would have the following structure:

101

2. Creating Maven-Eclipse Project
In Eclipse IDE, create a Maven project named HibernateMany2ManyAnnotationsExample
with the following structure:

This project consists of the following files:
Model classes: Group.java and User.java
Hibernate XML configuration file: hibernate.cfg.xml
Test program: UsersManager.java
Maven project: pom.xml
For the JAR files required for Hibernate and MySQL-Java library, update the pom.xml file with
the following content.
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.codejava.hibernate</groupId>
<artifactId>HibernateMany2ManyAnnotationsExample</artifactId>
<version>1.0</version>
<name>HibernateMany2ManyAnnotationsExample</name>
<description>A sample project that demonstrates using JPA annotations to map
a many-to-many association in Hibernate</description>

<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.7.SP1</version>
102

</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
</dependencies>

</project>
Here, we specify only two dependencies for Hibernate core and MySQL Connector/J, and the
rest will be resolved automatically by Maven, such as Hibernate JPA and Hibernate Commons
Annotations.
3. Using Annotations for Many-to-Many Association
To use JPA annotations to map the many-to-many association, create two model classes called
Group.java and User.java with the following source code:
File net\codejava\hibernate\Group.java:
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "GROUPS")
public class Group {
private long id;
private String name;

private Set<User> users = new HashSet<User>();

public Group(String name) {
this.name = name;
103

}

public void addUser(User user) {
this.users.add(user);
}

@Id
@GeneratedValue
@Column(name = "GROUP_ID")
public long getId() {
return id;
}

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "USERS_GROUPS",
joinColumns = @JoinColumn(name = "GROUP_ID"),
inverseJoinColumns = @JoinColumn(name = "USER_ID")
)
public Set<User> getUsers() {
return users;
}

// other getters and setters...
}
File net\codejava\hibernate\User.java:
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "USERS")
public class User {
private long id;
private String username;
private String password;
104

private String email;

private Set<Group> groups = new HashSet<Group>();

public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}

public void addGroup(Group group) {
this.groups.add(group);
}

@Id
@GeneratedValue
@Column(name = "USER_ID")
public long getId() {
return id;
}

@ManyToMany(mappedBy = "users")
public Set<Group> getGroups() {
return groups;
}

// other getters and setters...
}
We can see that both the Group and User classes have a collection (Set) of elements of each
other, thus this association is bidirectional. Here, the Group is the owner side and the User is the
other side.
To map this many-to-many association, these JPA annotations are used: @ManyToMany,
@JoinTable and @JoinColumn, besides the basic annotations (@Entity, @Column, @Id, etc)
. Lets look at these annotations on each side closely:
On the owner side (Group):
private Set<User> users = new HashSet<User>();

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "USERS_GROUPS",
joinColumns = @JoinColumn(name = "GROUP_ID"),
inverseJoinColumns = @JoinColumn(name = "USER_ID")
105

)
public Set<User> getUsers() {
return users;
}
Here, the @JoinTable annotation is used to specify the details of the join table (table
name and two join columns - using the @JoinColumn annotation). The cascade attribute
of the @ManyToMany annotation is required, so that Hibernate will update the
associated users when the group is updated.
On the other side (User):
1
2
3
4
5
6
private Set<Group> groups = new HashSet<Group>();

@ManyToMany(mappedBy = "users")
public Set<Group> getGroups() {
return groups;
}
This side is much simpler than the owner side, as we only need to specify the mappedBy
attribute of the @ManyToMany annotation. That means this groups collection is
mapped by the users collection on the owner side.
Implementing a Unidirectional Many-to-Many Association
To make direction of the association becomes unidirectional, simply remove the groups
collection from the User class:
@Entity
@Table(name = "USERS")
public class User {
private long id;
private String username;
private String password;
private String email;

public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}

@Id
@GeneratedValue
@Column(name = "USER_ID")
public long getId() {
return id;
106

}

// other getters and setters...
}
4. Writing Hibernate Configuration File
Create Hibernate XML configuration file (hibernate.cfg.xml) under the classpath with the
following content:
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/usersdb</property>
<property name="connection.username">root</property>
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping class="net.codejava.hibernate.User"/>
<mapping class="net.codejava.hibernate.Group"/>

</session-factory>
</hibernate-configuration>
Here, we specify database connection settings and the mapping classes to be loaded.
5. Writing a Test Program
So far we have done the association mapping part. To know if the mapping works as expected,
lets write a small program to insert some sample data with the following code
(UsersManager.java):
package net.codejava.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

107

/**
* A program that demonstrates using JPA annotations to map
* a bidirectional many-to-many association in Hibernate framework.
* @author www.codejava.net
*
*/
public class UsersManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration
.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Group groupAdmin = new Group("Administrator Group");
Group groupGuest = new Group("Guest Group");

User user1 = new User("Tom", "tomcat", "tom@codejava.net");
User user2 = new User("Mary", "mary", "mary@codejava.net");

groupAdmin.addUser(user1);
groupAdmin.addUser(user2);

groupGuest.addUser(user1);

user1.addGroup(groupAdmin);
user2.addGroup(groupAdmin);
user1.addGroup(groupGuest);

session.save(groupAdmin);
session.save(groupGuest);

session.getTransaction().commit();
session.close();
}

}
108

Output of the program:
1
2
3
4
5
6
7
Hibernate: insert into GROUPS (name) values (?)
Hibernate: insert into USERS (email, password, username) values (?, ?, ?)
Hibernate: insert into USERS (email, password, username) values (?, ?, ?)
Hibernate: insert into GROUPS (name) values (?)
Hibernate: insert into USERS_GROUPS (GROUP_ID, USER_ID) values (?, ?)
Hibernate: insert into USERS_GROUPS (GROUP_ID, USER_ID) values (?, ?)
Hibernate: insert into USERS_GROUPS (GROUP_ID, USER_ID) values (?, ?)
Result in the groups table:

Result in the users table:

Result in the join table users_groups:








109

Hibernate One-to-Many Association Annotations Example
This Hibernate tutorial will take you go through an example of mapping a one-to-many
association using JPA annotations - an alternative to XML descriptor approach which is
described in the Hibernate One-to-Many XML Mapping Example tutorial.
Lets look at the following entity relationship diagram to recall about the one-to-many
association:

Here, the multiplicity between the two entities category and product is one-to-many, meaning
that a category can have one or many products. This one-to-many association is constrained by
the foreign key in the product table.
The following software programs and libraries are used in order to develop a sample Hibernate
application that implements the one-to-many association above:
Hibernate 4.2.7.SP1
JDK 7
Eclipse IDE 4.3 (Kepler)
Maven 3
MySQL Community Server 5.5.23
MySQL Connector Java driver 5.1.26
Of course you can use similar versions. Heres the summary of steps which we are going to
follow:
Table of content:
1. Creating Database and Tables
2. Creating Maven-Eclipse Project
3. Annotating Model Classes for One-to-Many Association
4. Writing Hibernate Configuration File
5. Writing a Test Program

1. Creating Database and Tables
110

Execute the following MySQL script to create a database stockdb and two tables category and
product:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create database stockdb;
use stockdb;

CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`)
);

CREATE TABLE `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`description` varchar(512) NOT NULL,
`price` float NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`product_id`),
KEY `fk_category` (`category_id`),
CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category`
(`category_id`)
);
The structure of the stockdb database would look like this:


2. Creating Maven-Eclipse Project
In Eclipse IDE, create a Maven project named HibernateOne2ManyAnnotationsExample with
the following structure:
111


This project consists of the following files:
Model classes: Category.java and Product.java
Hibernate XML configuration file: hibernate.cfg.xml
Test program: StockManager.java
Maven project: pom.xml
Note that when using annotations approach, the XML mapping files for the model classes are no
longer needed. For JAR files of Hibernate and MySQL Connector/J, update the pom.xml file as
follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.codejava.hibernate</groupId>
<artifactId>HibernateOne2ManyAnnotationsExample</artifactId>
<version>1.0</version>
<description>Example of a Hibernate one-to-many association mapping
using annotations</description>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.7.SP1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
112

22
23
24
</dependency>
</dependencies>
</project>
And Maven will resolve related dependencies if any.



3. Annotating Model Classes for One-to-Many Association
Create two model classes called Category.java and Product.java with the following source code:
File net\codejava\hibernate\Category.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package net.codejava.hibernate;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;


@Entity
@Table(name = "CATEGORY")
public class Category {

private long id;
private String name;

private Set<Product> products;

public Category() {
}
113

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

public Category(String name) {
this.name = name;
}

@Id
@Column(name = "CATEGORY_ID")
@GeneratedValue
public long getId() {
return id;
}

@OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
public Set<Product> getProducts() {
return products;
}

// other getters and setters...
}

Recommended Book: Hibernate Made Easy: Simplified Data Persistence with Hibernate
and JPA (Java Persistence API) Annotations

File net\codejava\hibernate\Product.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package net.codejava.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "PRODUCT")
public class Product {
private long id;
private String name;
private String description;
private float price;
114

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

private Category category;

public Product() {
}

public Product(String name, String description, float price,
Category category) {
this.name = name;
this.description = description;
this.price = price;
this.category = category;
}

@Id
@Column(name = "PRODUCT_ID")
@GeneratedValue
public long getId() {
return id;
}

@ManyToOne
@JoinColumn(name = "CATEGORY_ID")
public Category getCategory() {
return category;
}

// other getters and setters...
}
Note that, the Category class has a set of Products, and the Product has a reference back to the
Category.
And, as we can see, only JPA annotations are used to annotate the model classes. The @Entity,
@Table, @Column, @Id and @GeneratedValue annotations are self-explanatory and easy to
understand. They are the basic elements needed for annotating any entities in Hibernate,
regardless of the association. We pay attention to the annotations that make the one-to-many
association: @OneToMany, @ManyToOne and @JoinColumn. Lets look at the code closely:
In the Category side:
1
2
3
4
5
private Set<Product> products;

@OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
public Set<Product> getProducts() {
return products;
115

6 }
Here, the mappedBy attribute is mandatory, as it specifies that the one-to-many
association is mapped by this side (Category); and the cascade attribute make sure
Hibernate will save/update the products set when saving/updating this category.
In the Product side:
1
2
3
4
5
6
7
private Category category;

@ManyToOne
@JoinColumn(name = "CATEGORY_ID")
public Category getCategory() {
return category;
}
Here, the @JoinColumn annotation specifies the join column of the association. It is
also mandatory.
Therefore, remember the key annotations are used for mapping a one-to-many association:
@OneToMany, @ManyToOne and @JoinColumn.



4. Writing Hibernate Configuration File
Configure database connection settings and mapping classes in the hibernate.cfg.xml file as
follows:
1
2
3
4
5
6
7
8
9
10
<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/stockdb</property>
<property name="connection.username">root</property>
116

11
12
13
14
15
16
17
18
19
<property name="connection.password">secret</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>

<mapping class="net.codejava.hibernate.Category"/>
<mapping class="net.codejava.hibernate.Product"/>

</session-factory>
</hibernate-configuration>

5. Writing a Test Program
So far we have finished the configuration part. Now, lets write a test program
(StockManager.java) with the following source code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.codejava.hibernate;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

/**
*
* This program demonstrates using JPA annotations in Hibernate
* in order to implement a one-to-many association mapping.
* @author www.codejava.net
*
*/
public class StockManager {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistryBuilder registry = new ServiceRegistryBuilder();
registry.applySettings(configuration.getProperties());
ServiceRegistry serviceRegistry = registry.buildServiceRegistry();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

117

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Category category = new Category("Computer");

Product pc = new Product("DELL PC", "Quad-core PC", 1200, category);

Product laptop = new Product("MacBook", "Apple High-end laptop", 2100, category);

Product phone = new Product("iPhone 5", "Apple Best-selling smartphone", 499,
category);

Product tablet = new Product("iPad 3", "Apple Best-selling tablet", 1099, category);

Set<Product> products = new HashSet<Product>();
products.add(pc);
products.add(laptop);
products.add(phone);
products.add(tablet);

category.setProducts(products);

session.save(category);

session.getTransaction().commit();
session.close();
}
}
Output of the program:
1
2
3
4
5
Hibernate: insert into CATEGORY (name) values (?)
Hibernate: insert into PRODUCT (CATEGORY_ID, description, name, price) values (?, ?, ?, ?)
Hibernate: insert into PRODUCT (CATEGORY_ID, description, name, price) values (?, ?, ?, ?)
Hibernate: insert into PRODUCT (CATEGORY_ID, description, name, price) values (?, ?, ?, ?)
Hibernate: insert into PRODUCT (CATEGORY_ID, description, name, price) values (?, ?, ?, ?)
Result in the category table:

Result in the product table:
118



Hibernate Basics - 3 ways to delete an entity from the datastore
This Hibernate basics tutorial shows you three different ways to remove an entity from the
datastore. Suppose that we have the following entity relationship (one-to-many):

A category can contain one or many products. The following MySQL script creates the database
and the two tables:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create database stockdb;
use stockdb;

CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`)
);

CREATE TABLE `product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`description` varchar(512) NOT NULL,
`price` float NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`product_id`),
KEY `fk_category` (`category_id`),
CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category`
(`category_id`)
);
119

As normal, we use JPA annotations to annotate the model classes:
Category.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package net.codejava.hibernate;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;


@Entity
@Table(name = "CATEGORY")
public class Category {

private long id;
private String name;

private Set<Product> products;

public Category() {
}

public Category(String name) {
this.name = name;
}

@Id
@Column(name = "CATEGORY_ID")
@GeneratedValue
public long getId() {
return id;
}

@OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
public Set<Product> getProducts() {
return products;
}

// other getters and setters...
120

43 }



Product.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package net.codejava.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "PRODUCT")
public class Product {
private long id;
private String name;
private String description;
private float price;

private Category category;

public Product() {
}

public Product(String name, String description, float price,
Category category) {
this.name = name;
this.description = description;
this.price = price;
this.category = category;
}

121

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Id
@Column(name = "PRODUCT_ID")
@GeneratedValue
public long getId() {
return id;
}

@ManyToOne
@JoinColumn(name = "CATEGORY_ID")
public Category getCategory() {
return category;
}

// other getters and setters...
}
We need to delete an individual product or a category with associated products. Lets see how to
accomplish this requirement using Hibernate APIs.

1. Deleting a transient instance
The Session.delete(Object) method allows us to remove a transient instance of the entity with an
identifier associated with existing persistent state. A transient instance is the one which does not
associate with the session. For example, the following statements delete a product whose
identifier equals to 37:
1
2
3
Product product = new Product();
product.setId(37);
session.delete(product);
Hibernate issues this query:
1 Hibernate: delete from PRODUCT where PRODUCT_ID=?
This way is simple and straightforward, because we dont have to load a persistent instance from
the datastore before deleting it. However, its drawback is that it doesnt remove the associated
instances, even an appropriate cascade type is specified in the class mappings/annotations.
Consider the following statements:
1
2
3
Category cat = new Category();
cat.setId(17);
session.delete(cat);
122

If the category (ID=17) is associated with some products (in the datastore), the code will throws
a ConstraintViolationException at runtime because Hibernate attempts to remove only the
category while it is still referenced by some products. We would see an error message like this:
1
2
ERROR: Cannot delete or update a parent row: a foreign key constraint fails
(`stockdb`.`product`, CONSTRAINT `fk_category` FOREIGN KEY (`category_id`)
REFERENCES `category` (`category_id`))
How to solve this problem is covered next.

Recommended Book: Hibernate Made Easy: Simplified Data Persistence with Hibernate
and JPA (Java Persistence API) Annotations

2. Deleting a persistent instance
In this way, we load a persistent instance using the Session.load(Class, ID) method before
deleting it. For example, the following code snippet solves the above problem of deleting a
category with associated products:
1
2
3
4
5
Serializable id = new Long(17);
Object persistentInstance = session.load(Category.class, id);
if (persistentInstance != null) {
session.delete(persistentInstance);
}
Hibernate issues these queries:
1
2
3
4
5
Hibernate: select category0_.CATEGORY_ID as CATEGORY1_0_0_, category0_.name as ...
Hibernate: select products0_.CATEGORY_ID as CATEGORY5_0_1_,
products0_.PRODUCT_ID ...
Hibernate: delete from PRODUCT where PRODUCT_ID=?
Hibernate: delete from PRODUCT where PRODUCT_ID=?
Hibernate: delete from CATEGORY where CATEGORY_ID=?
Using this technique, we tend to write a utility method like this:
1
2
3
4
5
6
private boolean deleteById(Class<?> type, Serializable id) {
Object persistentInstance = session.load(type, id);
if (persistentInstance != null) {
session.delete(persistentInstance);
return true;
}
123

7
8
return false;
}
Usage example:
1 boolean result = deleteById(Product.class, new Long(41));

Recommended Book: Java Persistence with Hibernate

3. Using Hibernate Query Language (HQL)
In this way, we use HQL to delete entities with more flexibility, such as removing products
whose prices are greater than a specified amount. For example:
1
2
3
4
5
6
7
8
Query query = session.createQuery("delete Product where price > :maxPrice");
query.setParameter("maxPrice", new Float(1000f));

int result = query.executeUpdate();

if (result > 0) {
System.out.println("Expensive products was removed");
}
Hibernate issues this query:
1 Hibernate: delete from PRODUCT where price>?
As you can see, Hibernate issues only one DELETE query, in contrast with the first two
approaches in which Hibernate issues a SELECT query first, then to DELETE. However, this
approach doesnt remove associated instances. Consider the following example:
1
2
3
4
Query query = session.createQuery("delete Category where id = :ID");
query.setParameter("ID", new Long(18));

int result = query.executeUpdate();
A ConstraintViolationException will be thrown at runtime if the category associates with some
products. In this case, we have to write two queries: the first is to remove the products and the
second is to remove the category.
124

So far we have looked at the three different ways of deleting entities from the datastore using
Hibernate APIs. Each has its own pros and cons, so its up to you to decide which best suites
your need.
Hibernate Enum Type Mapping Example
This tutorial shows you how to map an enum type from Java to a column in database with
Hibernate ORM framework. Its very common that a database column stores enumerated values
such as gender (male or female), status (new, in progress, closed), etc. Hibernate makes that easy
to implement. Lets see the basic elements are used for enum type mapping, in both annotation
and XML.
Suppose that we have a database table called person which can be created by executing the
following MySQL script:
1
2
3
4
5
6
CREATE TABLE `person` (
`person_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`gender` int(4) NOT NULL,
PRIMARY KEY (`person_id`)
)
Here, the column gender can hold value in a specified range (enumeration), e.g. 0 for male and 1
for female.
In Java side, we have a model class called Person as shown below:
1
2
3
4
5
6
7
public class Person {
private int id;
private String name;
private Gender gender;

// getters and setters...
}
Here, the gender attribute is an enumeration type, which is declared as below:
1
2
3
public enum Gender {
MALE, FEMALE
}
Now, we want to map this enumeration type to the column gender in the database. Lets see how
to do that in Hibernate.

125

1. Using @Enumerated Annotation
We can use the JPAs @Enumerated annotation to annotate the getter method of the gender
attribute as follows:
1
2
3
4
@Enumerated(EnumType.ORDINAL)
public Gender getGender() {
return gender;
}
If the database column is of type number (integer), we should use the EnumType.ORDINAL
parameter which tells Hibernate to insert values according to order of the enum constant. For
example, if the MALE is the first constant then 0 will be inserted; if the FEMALE is the second
then 1 will be inserted, and so on.
In case the database column is of type character (varchar), the EnumType.STRING should be
used. For example:
1
2
3
4
@Enumerated(EnumType.STRING)
public Gender getGender() {
return gender;
}
Then Hibernate will insert name of the enum constant, e.g. MALE and FEMALE to the
database.
Recommended Book: Java Persistence with Hibernate

2. Using XML Mapping
In case XML mapping is used instead of annotations, declare mapping for the gender column as
following:
1
2
3
4
5
<property name="gender" column="GENDER">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">net.codejava.hibernate.Gender</param>
</type>
</property>
Thats equivalent to usage of the EnumType.ORDINAL parameter with annotations.
The following XML mapping snippet is equivalent to usage of the EnumType.STRING
parameter:
126

1
2
3
4
5
6
<property name="gender" column="GENDER">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">net.codejava.hibernate.Gender</param>
<param name="useNamed">true</param>
</type>
</property>
Note that, some document says <param name="type">12</param> for mapping to a varchar
column. However, using the useNamed attribute is much more descriptive.

3. Annotating Model Class
The following snippet is code of the Person class which is annotated using JPA annotations:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.codejava.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
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 Gender gender;

public Person(String name, Gender gender) {
this.name = name;
this.gender = gender;
}

@Id
@Column(name = "PERSON_ID")
@GeneratedValue
public int getId() {
return id;
}

127

31
32
33
34
35
36
37
@Enumerated(EnumType.ORDINAL)
public Gender getGender() {
return gender;
}

// other getters and setters
}
Here, code of other getters and setters are removed for brevity.

4. Writing Test Class
Below is code of a console program that tries to save two persons (male and female) to the
database.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package net.codejava.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;

public class HibernateTest {

public static void main(String[] args) {
// loads configuration and mappings
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry
= new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();

// builds a session factory from the service registry
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

// obtains the session
Session session = sessionFactory.openSession();
session.beginTransaction();

Person malePerson = new Person("Tom", Gender.MALE);
session.save(malePerson);

Person femalePerson = new Person("Mary", Gender.FEMALE);
session.save(femalePerson);
128

30
31
32
33
34
35
36
37
38

session.getTransaction().commit();
session.close();

StandardServiceRegistryBuilder.destroy(serviceRegistry);

}

}
The result can be seen using MySQL console as in the following screenshot:


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.
Lets 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:
1
2
3
4
5
6
7
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`)
129

8 )
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:
Heres the model class (Person.java) that uses JPA annotations for mapping:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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;
}
130

34
35
36
37
38
39
40

public void setPhoto(byte[] photo) {
this.photo = photo;
}

// other getters and setters
}

Recommended Book: Hibernate Made Easy: Simplified Data Persistence with Hibernate
and JPA (Java Persistence API) Annotations

Model Class with a java.sql.Blob type:
Heres another version of the model class in case the java.sql.Blob type is used:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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")
131

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@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):
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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:
1 <property name="photo" column="PHOTO" type="binary" />
For java.sql.Blob:
132

1 <property name="photo" column="PHOTO" type="blob" />
Its better to let Hibernate decides the appropriate mapping type.

Recommended Book: Java Persistence with Hibernate

3.Test Programs
Here is code of a test program for the case in which a primitive byte[] array is used:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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);

133

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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();
}

134

79
80
81
82
83
84
85
private static void endSession() {
session.getTransaction().commit();
session.close();

StandardServiceRegistryBuilder.destroy(serviceRegistry);
}

}
And the following programs code is for the case in which a java.sql.Blob is used:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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();

135

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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() {
136

82
83
84
85
86
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.

Вам также может понравиться