Hibernate Tutorial
Hibernate Tutorial
This hibernate tutorial provide step by step instructions on using Hibernate 3.0. Hibernate is popular open
source object relational mapping tool for Java platform. It provides powerful, ultra-high performance
object/relational persistence and query service for Java.
Actually Hibernate is much more than ORM Tool (Object - Relational Mapping) because today its provide
lots of features in the persistence data layer.
ORM means Objects to Relational Mapping i.e. Java Persistence Objects are mapped to Relational
databases by using ORM tools.
HIBERNATE :
An ORM Tool
Implements JPA (Java Persistence API) i.e its have set of standards that have been prescribed
for any persistence of any implementation need to be satisfied to persistence rules in the java that given
minimal change of codes means follow the all rules of persistence in later if any change in the ORM tools
with minimum change in the code.
Here there is one problem to object save in to relational database each entity of the object save
individually to the database table in the associated columns. It is more times taken and complex in case
of lots of user objects to be save into the database table.
Session:Session objects provide the main interface to accomplish work with the
database. Persistent objects are saved and retrieved through a Session object. A
Session object is lightweight and inexpensive to create. A Session object does the work
of getting a physical connection to the database. Session objects maintain a cache for a
single application thread (request).
Session objects are not thread safe. Therefore, session objects should not be kept open
for a long time.Applications create and destroy these as needed. Typically, they are
created to complete a single unit of work, but may span many units. -Dinesh
Transaction: represents unit of works.
Query and Criteria objects are used to retrieve (and recreate) persistent objects.
In this tutorial you will see how to configure Hibernate to Eclipse or STS or MyEclipse.
1.
Download Eclipse Latest version and install in your machine.
2.
Download Hibernate3 Latest Version.
3.
Download MySQL database Latest version.
4.
Download JConnector (MySQL Database Driver)
Step 1 : Now open Eclipse you get following window-
Step 5:Right Click on Hibernate Project->go to Property ->Java Build Path->Library->Add Library
Step 7: Click on Add JARs.. go to specific path of the window where you are save Hibernate Zip file and
add following required jar to your Application
antlr-2.7.6
dom4j-1.6.1
hibernate3
hsqldb
javassist-3.4.GA
jta-1.1
slf4j-api-1.5.6
slf4j-simple-1.5.6
commons-collections-3.1
Step 8 : Now install MySQL Database on your machine and add driver library to your application
Go to Project Property->Java Build Path->Library->Add External JARs..->Select Driver jar file>click finish
Database Design
DAO method to use saving the model object to the database using SQL queries.
With Hibernate Way->
Service method to create the model object -> Using the Hibernate API
DAO method to use saving the model object to the database using SQL queries -> Not needed
Now as above steps of using hibernate, firstly we have to create Hibernate Configuration file.
Step 1: File Name -> hibernate.cfg.xml in src folder of the application
Now we need to type all the detail related to MySQL database so we can use in our application.
hibernate.cfg.xml
<?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">
<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/hibernateDB</property>
<property name="connection.username">username</property>
<property name="connection.password">password</property>
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Show all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails"/>
</session-factory>
</hibernate-configuration>
Here below property configure driver of the specific database
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
Next line we configure the Database connection url
suppose we want to connect the database name hibernateDB
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB</property>
Next two lines set the user name and password of the connecting database hibernateDB
<property name="connection.username">username</property>
<property name="connection.password">password</property>
Next line configure Dialect of the database MySQL, every database has its own Dialect.
What is Dialect? means Dialect is configuration specify here so hibernate knows whats kind of language
we are used and what type database we are used. we can say it is database dependent. It connects the
database specific query language which we want to use.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
The below line configured the model class name UserDetails its object we want save on the
database hibernateDB
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails"/>
Now step 1 is over now we move to another step Now we have to create a Model class
Step 2: UserDetails.java
package com.sdnext.hibernate.tutorial.dto;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class UserDetails
{
@Id
private int userId;
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Here @Entity means it telling hibernate this class treat as entity and need to save it the database.
and @ID means it telling hibernate this property treat as primary key of the table.
these are two minimum required annotation we have use for saving the object in the database.
Now we move to next step create service method to save the model object in the database.
Using the Hibernate API
Next Chapter we will write hibernate application using mapping file for the model class
In the Next Chapter We will Described the O/R Mapping file in details.
2.
Another way Using Hibernate O/R Mapping file(.hbm.xml) for Model Class Object
Mapping.
In the last example we created userDetails.hbm.xml to map UserDetails Object to
the UserDetails table in the database. Now let's understand the each component of the mapping file.
To recall here is the content of userDetails.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.sdnext.hibernate.tutorial.dto.UserDetails" table="UserDetails">
<id name="userId" type="long" column="ID" >
<generator class="assigned"/>
</id>
<property name="userName">
<column name="UserName" />
</property>
</class>
</hibernate-mapping>
1.<hibernate-mapping> element:
The first or root element of hibernate mapping document is <hibernate-mapping> element. Between the
<hibernate-mapping> tag class element(s) are present.
2. <class> element:
The <Class> element maps the class object with corresponding entity in the database. It also tells what
table in the database has to access and what column in that table it should use. Within one <hibernatemapping> element, several <class> mappings are possible.
3.<id> element:
The <id> element in unique identifier to identify an object. In fact <id> element map with the primary key
of the table. In our code :
<id name="userId" type="long" column="ID" >
primary key maps to the ID field of the table UserDetails. Following is the attributes of <id> element
column - Name of the column for that property of the persistence object
unsaved-value - This is the value used to determine if a class has been made persistent. If the
value of the id attribute is null, then it means that this object has not been persisted.
4.<generator> element:
Used to create primary key for new record, there are some commonly used generators type given below...
Increment- used to generate primary keys of type long, short or int that are unique only.
Sequence - used to generate primary keys for DB2, Oracle, SAP Database.
Native
- selects identity, sequence or hilo depending upon the capabilities of the underlying db.
Identity - supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL.
The returned identifier is of type long, short or int.
Uuid - Unique use ID of 128 bits generated from using algorithm and return type is String
5.<property> element: define standard Java attributes and their mapping into database schema.
That is all about the mapping file for O/R mapping. I hope you was understand its all elements and its
working in the hibernate.
MAPPING:
Every ORM tool needs this mapping, mapping is the mechanism of placing an object properties
into columns of a table.
Mapping can be given to an ORM tool either in the form of an XML or in the form of the
annotations.
The mapping file contains mapping from a pojo class name to a table name and pojo class
variable names to table column names.
While writing an hibernate application, we can construct one or more mapping files, mean a
hibernate application can contain any number of mapping files.
generally an object contains 3 properties like
XML
Annotations.
Actually annotations are introduced into java from JDK 1.5
here @Entity declares the class as an entity (i.e. a persistent POJO class)
@Table is set at the class level; it allows you to define the table, catalog, and schema names for your
entity mapping. If no@Table is defined the default values are used: the unqualified class name of the
entity.
Mapping primary key USER_ID of table to property userId of class UserDetails in XML
<id name="userId" type="long" column="USER_ID" >
Mapping primary key USER_ID of table to property userId of class UserDetails in Annotation
@Entity
@Table (name="USER_DETAILS")
public class UserDetails
{
@Id
@Column(name="USER_ID")
SEQUENCE - sequence
@GeneratedValue Provides for the specification of generation strategies for the values of primary keys.
Enum GenerationType Defines the types of primary key generation strategies.
Mapping Column to the property of class in XML
<property name="userName" column="USER_NAME">
@Basic
private String userName;
@Transient - using when if you want skip any field of entity class to save in the database. Example@Transient
private String middleName;
@Embedded- using when if property or field of persistence class is Embeddable persistence class.
Example- class Address{ @Column(name="STREET")
@Embedded
private Address address;
@ElementColllection- Defines a collection of instances of a basic type or embeddable class. Must be
specified if the collection is to be mapped by means of a collection table. Example@ElementCollection
private Collection<Address> lisOfAddresses = new ArrayList<Address>();
@Id- Specifies the primary key of an entity. Example@Id
private long userId;
@EmbeddedId- composite primary key of an embeddable class. Example@Embeddable
Class Address{
@EmbeddedId
private int addressId;
------}
@Version- Specifies the version field or property of an entity class that serves as its optimistic lock value.
The version is used to ensure integrity when performing the merge operation and for optimistic
concurrency control. Example-
@Version
private int addressId;
@Temporal- This annotation must be specified for persistent fields or properties of
type java.util.Date andjava.util.Calendar. Example@Column(name="JOIN_DATE")
@Temporal(TemporalType.DATE)
private Date joinDate;
Here we will learn about hbm2ddl Configuration in the hibernate configuration file (hibernate.cfg.xml).
Actually hbm2ddl Configuration means hibernate mapping to create schema DDL (Data Definition
Language).
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
Automatically validates or exports schema DDL to the database when the SessionFactory is created.
With create-drop, the database schema will be dropped when the SessionFactory is closed
explicitly.
<?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">
<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/hibernateDB</property>
<property name="connection.username">username</property>
<property name="connection.password">password</property>
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Show all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
session.getTransaction().commit();
session.close();
}
}
Run this example-log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?)
Hibernate: insert into USER_DETAILS ( USER_ID, USER_NAME) values (?, ?)
Now we get the following table schema--
Here we see that the previous data is destroyed when we are using in the hibernate.cfg.xml file using
the following line.
<property name="hbm2ddl.auto">create</property>
Here
hbm2ddl.auto-->create -Always create new schema
hbm2ddl.auto-->update -Update existing schema
Now we are replacing above line with the <property name="hbm2ddl.auto">update</property>
public class HibernateTestDemo {
public static void main(String[] args)
{
//Create the model object
UserDetails user1 = new UserDetails();
UserDetails user2 = new UserDetails();
user1.setUserId(1);
user1.setUserName("Dinesh Rajput");
user2.setUserId(2);
user2.setUserName("Anamika Rajput");
// Create Session Factory Object - using annotation configuration object
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
//Create Session object from session factory object
Session session = sessionFactory.openSession();
session.beginTransaction();
//Use the session to save model objects
session.save(user1);
session.save(user2);
session.getTransaction().commit();
session.close();
}
}
here we are looking the table USER_DETAILS only updated not again created.
</session-factory>
</hibernate-configuration>
here we are using MySql database hibernateDB. Now we running the code with following class file
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = new UserDetails(); //Creating first user
user.setUserId(1);
user.setUserName("Dinesh Rajput");
UserDetails user2 = new UserDetails();//Creating second user
user2.setUserId(2);
user2.setUserName("Anamika Rajput");
SessionFactory sessionFactory = new
AnnotationConfiguration().configure().buildSessionFactory(); //Creating a session factory object
Session session = sessionFactory.openSession(); //Creating a session object for inserting
users object to the database table USER_TABLE
session.beginTransaction(); //Open the transaction of session object to do something
session.save(user); //Inserting or Saving the first user
object
session.save(user2); //Inserting or Saving the second user object
session.getTransaction().commit();//Close the transaction of session object after to do
something
session.close(); //Close the session object performing saving event to database
user = null; //Now getting a user object from database table from session object
session = sessionFactory.openSession(); //Creating a new session object for fetching user
object
session.beginTransaction(); //Again Open the transaction of the session object
user = (UserDetails) session.get(UserDetails.class, 1); //we get user object from session object
using method session.get(Class arg1, Serializable arg2) here arg2 is primary key or id of the
fetching object and arg1 is the what the model object we want to retrieve from database.
System.out.println(user);
}
}
Here after running this code we get following output...
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_TABLE (USER_NAME, USER_ID) values (?, ?)
Hibernate: insert into USER_TABLE (USER_NAME, USER_ID) values (?, ?)
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_
from USER_TABLE userdetail0_ where userdetail0_.USER_ID=?
[User Name: Dinesh Rajput User Id: 1]
In the above table we want to update the value of the USER_NAME column of the USER_TABLE table
associated user model object which userId = 2
current value of the userName is 'Anamika Rajput' update to userName='Sweety'.
Look the following class file.
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = null;
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
user = (UserDetails) session.get(UserDetails.class, 2); //Retrieving object which we want to update
user.setUserName("Sweety"); //Set the updated userName to the model field
session.update(user); //Update to the database table
session.getTransaction().commit();
System.out.println("Updated User ->"+user);
session.close();
}
}
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_
from USER_TABLE userdetail0_ where userdetail0_.USER_ID=?
Hibernate: update USER_TABLE set USER_NAME=? where USER_ID=?
[Updated User -> User Name: Sweety User Id: 2]
We are looking the value of the USER_NAME column updated from 'Anamika Rajput' to 'Sweety' in
the USER_TABLE table.
Following is USER_TABLE:
package com.sdnext.hibernate.tutorial;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
String sql = "DELETE FROM UserDetails WHERE USER_ID = 2";
Query query = session.createQuery(sql);
int row = query.executeUpdate();
if (row == 0)
System.out.println("Doesnt deleted any row!");
else
System.out.println("Deleted Row: " + row);
session.getTransaction().commit();
session.close();
}
}
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: delete from USER_TABLE where USER_ID=2
Deleted Row: 1
Well learn the difference between Entity type objects and Value type objects. Well use
the @Embeddable annotations to embed a value type object into our Entity class.
"An object of value type has no database identity; it belongs to an entity instance and its persistent
state is embedded in the table row of the owning entity. Value types don't have identifiers or identifier
properties"
Now In short we look the following points...
Object of Value Type : belongs to an entity, and its persistent state is embedded in the table row
of the owning entity. Value types don't have identifiers or identifier properties.
We look following example of Object of Entity Type:
@Entity
@Table(name="USER_TABLE")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="USER_ID", type="INTEGER")
private long userId;
@Column(name="USER_NAME", type="String")
private String userName;
@Column(name=USER_ADDRESS, type="String")
private String address;
@Column(name="USER_PHONE", type="INTEGER")
private long phone;
@Column(name="DOB", type="TIMESTAMP")
private Date dob;
}
In Above table we saw that type of the all fields of the class USER CLASS have database entity type
object.
ID
is INTEGER type
Name
is VARCHAR type
ADDRESS is VARCHAR type
Phone
is BIG INTEGER type
DOB
is TIMESTAMP type
All are the Entity Type Objects.
Now We look following example of Object of Value Type:
@Entity
@Table(name="USER_TABLE")
public class UserDetails{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="USER_ID", type="INTEGER")
private long userId;
@Column(name="USER_NAME", type="String")
private String userName;
@Column(name=USER_ADDRESS, type="??????") //What should be type for database
private Address address;
@Column(name="USER_PHONE", type="INTEGER")
private long phone;
@Column(name="DOB", type="TIMESTAMP")
private Date dob;
}
Now lets see table structure for that...
here USER CLASS have a field Address type of the Value type object means in the database there are
no meaning of Address type object.
Address type object have the four other fields like.
1. Street
2. City
3. State
4. Pin code
VALUE TYPE OBJECT APPROACH:>
Here there are one approach to save the value the Address Object save to the USER TABLE is the save
the individually fields of this object to the separate columns of the USER TABLE. As following
This scenario is working in the hibernate only one condition is Address Object should be a Value Object
(means there is no meaning to itself its provide the meaning to the entity object).
In this approach there are some problems are
1. Table complexity
2. Data Redundancy
3. User may have multiple Address like home address and office address etc.
Look the above example in the code...
Address.java
package com.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable //for value object it is not is entity object. Value object means does not have real
meaning for self individually.
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table (name="USER_TABLE")
public class UserDetails
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="USER_ID")
private int userId;
@Column(name="USER_NAME")
private String userName;
@Embedded //For value type object
private Address address;
@Column(name="USER_PHONE")
private String phone;
@Column(name="DOB")
private Date dob;
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int getUserId() {
return userId;
}
public String toString()
{
return "[User Name: "+userName+"User Id: "+userId+" User Address "+address+" Use phone "
+phone+" ]";
}
}
hibernate.cfg.xml
<?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">
<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/hibernateDB</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails"/>
</session-factory>
</hibernate-configuration>
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.Address;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
OUTPUT:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_TABLE (CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME, DOB,
USER_PHONE, USER_NAME) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into USER_TABLE (CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME, DOB,
USER_PHONE, USER_NAME) values (?, ?, ?, ?, ?, ?, ?)
Attributes Override:
Here we have seen that an Entity Type Object USER has a Value Type Object(or Embeddable Object )
ADDRESS with corresponding fields name street, city, pin-code and state save to the database table
USER_TABLE with value type object's column name (CITY_NAME, PIN_CODE, STATE_NAME,
STREET_NAME).
But here some problems, suppose this user object have two types of addresses as like Local Address
and Permanent Address then how to manage the column names of these value type objects in the
database table USER_TABLE.
To overcome this problem we have to override the Attributes of the Value type objects.
Lets see how to get in the code...
UserDetails.java
package com.sdnext.hibernate.tutorial.dto;
import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
@Entity
@Table (name="USER_TABLE")public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
Suppose we want to keep tracks all addresses of an user, so think about one minute how to get.
Lets we will using the Collection for that.
1. In this code snip User has one address
class UserDetails{
----private int userId;
----private Address address;
----}
class UserDetails{
----private int userId;
----private List<Address> addresses = new ArrayList<Address>();
----}
Hibernate provides the facility to persist the collections. A collection can be a list, set, map, collection,
sorted set, sorted map. java.util.List, java.util.Set, java.util.Collection, java.util.SortedSet,
java.util.SortedMap etc. are the real interface types to declared the persistent collection-value fields.
Hibernate injects the persistent collections based on the type of interface. The collection instances usually
behave likes the types of value behavior. Instances of collections are auto persisted if a persistent object
refers it and are deleted automatically if it is not referred through. Elements of collection may shift from
one table to another when a persistent object passed the collection to another persistent object.
}
}
@ElementCollection:
Target:
Fields (including property get methods)
Defines a collection of instances of a basic type or embeddable class. Must be specified if the
collection is to be mapped by means of a collection table.
Address.java
package com.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable //for value object it is not is entity object. Value object means does not have real meaning
for self individually.
public class Address
{
@Column(name="STREET_NAME")
private String street;
@Column(name="CITY_NAME")
private String city;
@Column(name="STATE_NAME")
private String state;
@Column(name="PIN_CODE")
private String pincode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPincode() {
return pincode;
}
public void setPincode(String pincode) {
this.pincode = pincode;
}
public String toString()
{
return " {Street: "+street+" City: "+city+" State: "+state+" Pincode: "+pincode+" }";
}
}
hibernate.cfg.xml will be the same as the previous chapter.
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.Address;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = new UserDetails();//Create user object
user.setUserName("Dinesh Rajput"); //Set user name
Address address1 = new Address(); // create first embedded object address
address1.setStreet("First Street");
address1.setCity("First City");
address1.setState("First State");
address1.setPincode("First Pin");
Look care fully to the output line, there are two tables here in the database, first for the UserDetails entity
"TBL_USER_DETAILS" and second for the embeddable object Address name is
"TBL_USER_DETAILS_lisOfAddresses " (this is default name of table for address Entity Table
Name_field name of the list of the embeddable object in the entity class).
Here see that there is one table for the address object created separate for the collection.
1. First Table TBL_USER_DETAILS
In the second table first column TBL_USERS_DETAILS_USER_ID has the user id is foreign key for this
table and primary key of the TBL_USER_DETAILS table.
In this chapter we will explore some advanced options about the collection.
Now we see first thing is the name of the table.
TBL_USER_DETAILS_lisOfAddresses is name for the collection table it is not very user friendly name.
@JoinTable:
Target:
Fields (including property get methods)
Used in the mapping of associations. It is specified on the owning side of an association.
A join table is typically used in the mapping of many-to-many and unidirectional one-to-many
associations. It may also be used to map bidirectional many-to-one/one-to-many associations,
unidirectional many-to-one relationships, and one-to-one associations (both bidirectional and
unidirectional).
When a join table is used in mapping a relationship with an embeddable class on the owning side of the
relationship, the containing entity rather than the embeddable class is considered the owner of the
relationship.
If the JoinTable annotation is missing, the default values of the annotation elements apply. The name of
the join table is assumed to be the table names of the associated primary tables concatenated together
(owning side first) using an underscore.
@Entity
@Table (name="USERS_DETAILS")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@ElementCollection
@JoinTable(name="USER_ADDRESS")//name of the table is changed to USER_ADDRESS
private Collection<Address> lisOfAddresses = new ArrayList<Address>();
}
After running the above code the following output string show the updated table name of the collection
table.
Now we see that the name of the column of this table which have the foreign key user id is
the USER_DETAILS_USER_ID is not also very user friendly, for this look to the following updated code
of the UserDetails entity class. Here we used annotation@JoinColumn.
@JoinColumn:
Target:
@Entity
@Table (name="USERS_DETAILS")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@ElementCollection
@JoinTable(name="USER_ADDRESS",
joinColumns=@JoinColumn(name="USER_ID"))
private Collection<Address> lisOfAddresses = new ArrayList<Address>();
}
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
@Entity
@Table (name="USER_DETAIL")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@ElementCollection
@JoinTable(name="USER_ADDRESS",
joinColumns=@JoinColumn(name="USER_ID"))
@GenericGenerator(strategy="hilo", name = "hilo-gen")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "hilo-gen", type =
@Type(type="long"))
private Collection<Address> lisOfAddresses = new ArrayList<Address>();
public Collection<Address> getLisOfAddresses() {
return lisOfAddresses;
}
public void setLisOfAddresses(Collection<Address> lisOfAddresses) {
this.lisOfAddresses = lisOfAddresses;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String toString()
{
return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]";
}
}
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.Address;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = new UserDetails();
//user.setUserId(1);
user.setUserName("Dinesh Rajput");
Address address1 = new Address();
address1.setStreet("First Street");
address1.setCity("First City");
address1.setState("First State");
address1.setPincode("First Pin");
Address address2 = new Address();
address2.setStreet("Second Street");
address2.setCity("Second City");
address2.setState("Second State");
address2.setPincode("Second Pin");
user.getLisOfAddresses().add(address1);
user.getLisOfAddresses().add(address2);
Tables:
In our example user class has the three field values1. User Id
2. User Name
3. List of the Addresses
If you want retrieve user object from the database, so what field value are retrieved from the database
and which field are initialized. Suppose one user XYZ has the 100 addresses in the database and we
want to retrieved the name of this user from database. For that we retrieve the user object, now question
is this what about the field listOfAddress field, Is it also have the value? if you say yes so what about
cost of memory ? if you say no so how to retrieve the value associated with that field the address table in
the database on demand.
-A
|
*---B
|
|
|
*---C
|
|
|
*---D
|
|
|
*---E
|
|
|
*---F
|
|
|
*---G
*---H
Ok lets see in the given below flow of the diagram.
In Hibernate 2 does not proxy objects by default. However, experience has shown that using object
proxies is preferred, so this is the default in Hibernate 3.
In Hibernate 3, when we fetching the user object from the database actually its retrieved the proxy object
of the user class means only first level of the fields are initializing with the associated values from the
database. Field listOfAddresses does not have the value. If you want the list address you should call the
following method you will get the listOfAddresses.
user.getListOfAddress(); --->> this return the list of the address associated
with that particular user which name is XYZ this is the default behavior of the Hibernate 3.
Now we look about the fetching strategies.
Fetching Strategies: there are two types of the fetching strategies in the hibernate.
1. Lazy Fetch type
2. Eager Fetch type
LAZY = fetch when needed
EAGER = fetch immediately
1. Lazy Fetch Type: This the default fetch type of the hibernate 3.
Now when you load a User from the database, JPA loads its id, name, and address fields for you. But you
have two options for users: to load it together with the rest of the fields (i.e. eagerly) or to load it ondemand (i.e. lazily) when you call the user'sgetListOfAddresses() method.
Lazy/Select Fetch strategy:- Select Fetch strategy is the lazy fetching of associations. The purpose of
Lazy strategy is memory optimization . When I say memory optimization it means it means it saves us
from heap error. This is what I think. So we can say yes if we are loading too objects in aseesion we
should go for Lazy Fetch strategy but in terms of time performance it does not provide any Benefit.
Agreed?
When a user has many addresses it is not efficient to load all of its addresses with it when they are not
needed. So in suchlike cases, you can declare that you want addresses to be loaded when they are
actually needed. This is called lazy loading.
EXAMPLE: UserDetails.java
package com.sdnext.hibernate.tutorial.dto;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
@Entity
@Table (name="USER_DETAIL")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@ElementCollection(fetch=FetchType.LAZY)
@JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID"))
private Collection<Address> lisOfAddresses = new ArrayList<Address>();
public Collection<Address> getLisOfAddresses() {
return lisOfAddresses;
}
public void setLisOfAddresses(Collection<Address> lisOfAddresses) {
this.lisOfAddresses = lisOfAddresses;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String toString()
{
return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]";
}
}
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.Address;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = new UserDetails(); // create user object
//user.setUserId(1);
user.setUserName("Dinesh Rajput");
Address address1 = new Address(); // create address object
address1.setStreet("First Street");
address1.setCity("First City");
address1.setState("First State");
address1.setPincode("First Pin");
Address address2 = new Address(); // create another address object
address2.setStreet("Second Street");
address2.setCity("Second City");
address2.setState("Second State");
address2.setPincode("Second Pin");
user.getLisOfAddresses().add(address1); // set the addresses objects to list of the addresses
user.getLisOfAddresses().add(address2);
SessionFactory sessionFactory = new
AnnotationConfiguration().configure().buildSessionFactory(); // create session factory object
Session session = sessionFactory.openSession(); // create session object
session.beginTransaction(); // start transaction object
session.save(user); // save the user to database
session.getTransaction().commit(); // commit the transaction
session.close(); // closing session
session = sessionFactory.openSession(); // again create another session object
user = null;
user = (UserDetails) session.get(UserDetails.class, 1); // retrieved the user from the database for
particular user which user id = 2 this object it is proxy user object.
System.out.println(user.getLisOfAddresses().size());
}
}
******************************************************************************
OUTPUT:Look care fully the output has the two select query one is for user and another is for address
table when we callgetListOfAddresses();
2. Eager Fetch Strategy: In hibernate 2 this is default behavior of the to retrieving an object from the
database.
Eager/Join Fetch strategy:- Join Fetch strategy the eager fetching of associations.The purpose of Join
Fetch strategy is optimization in terms of time.I mean even associations are fetched right at the time of
fetching parent object. So in this case we dont make database call again and again . So this will be much
faster.Agreed that this will bad if we are fetching too many objects in a session because we can get java
heap error.
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
@Entity
@Table (name="USER_DETAIL")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@ElementCollection(fetch=FetchType.EAGER)
@JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID"))
private Collection<Address> lisOfAddresses = new ArrayList<Address>();
public Collection<Address> getLisOfAddresses() {
return lisOfAddresses;
}
public void setLisOfAddresses(Collection<Address> lisOfAddresses) {
this.lisOfAddresses = lisOfAddresses;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String toString()
{
return "[User Name: "+userName+"\n Office Address: "+lisOfAddresses+"]";
}
}
Now run the following code and see the output--package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.Address;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = new UserDetails();
//user.setUserId(1);
user.setUserName("Dinesh Rajput");
Address address1 = new Address();
address1.setStreet("First Street");
address1.setCity("First City");
address1.setState("First State");
address1.setPincode("First Pin");
Address address2 = new Address();
address2.setStreet("Second Street");
address2.setCity("Second City");
address2.setState("Second State");
address2.setPincode("Second Pin");
user.getLisOfAddresses().add(address1);
user.getLisOfAddresses().add(address2);
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
session = sessionFactory.openSession();
user = null;
OUTPUT:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_DETAIL (USER_NAME) values (?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME,
STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME,
STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as
USER2_0_0_, lisofaddre1_.USER_ID as USER1_2_, lisofaddre1_.CITY_NAME as CITY2_2_,
lisofaddre1_.PIN_CODE as PIN3_2_, lisofaddre1_.STATE_NAME as STATE4_2_,
lisofaddre1_.STREET_NAME as STREET5_2_ from USER_DETAIL userdetail0_ left outer join
USER_ADDRESS lisofaddre1_ on userdetail0_.USER_ID=lisofaddre1_.USER_ID where
userdetail0_.USER_ID=?
2******************************************************************************
See this is successfully run the code because we are using the EAGER fetching strategy so in this
strategy session return the original object with all field are initialized when load on the memory.
In the above output string look care fully there are only one select statement with join clause.
So now can we say in the hibernate session where we are not loading too many objects we should
go for Eager fetch as it will be much better in terms of time response(Any ways memory will be
reclaimed by garbage collector once we close the session).
Hibernate Mapping One-to-One:In this example you will learn how to map one-to-one relationship
using Hibernate. Consider the following relationship between UserDetails and Vehicle entity.
}
}
2. Create the User Class
UserDetails.java
package com.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table (name="USER_DETAIL")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@OneToOne
@JoinColumn(name="VEHICLE_ID")
private Vehicle vehicle;
public Vehicle getVehicle() {
return vehicle;
}
public void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
<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/hibernateDB</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails"/>
<mapping class="com.sdnext.hibernate.tutorial.dto.Vehicle"/>
</session-factory>
</hibernate-configuration>
In this chapter you will learn how to map one-to-many relationship using Hibernate. Consider the following
relationship betweenUserDetails Class and Vehicle entity.
In this example UserDetails class has the collection of the another entity class Vehicle. So the given
below diagram so table structure for that.
this.vehicleName = vehicleName;
}
}
2. Create the User Class
UserDetails.java
package com.sdnext.hibernate.tutorial.dto;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table (name="USER")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
@OneToMany
@JoinTable( name="USER_VEHICLE",
joinColumns=@JoinColumn(name="USER_ID"),
inverseJoinColumns=@JoinColumn(name="VEHICLE_ID")) //its optional using for name
configuration of the join table
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
public int getUserId() {
return userId;
}
public Collection<Vehicle> getVehicle() {
return vehicle;
}
public void setVehicle(Collection<Vehicle> vehicle) {
this.vehicle = vehicle;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
<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/hibernateDB</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails"/>
<mapping class="com.sdnext.hibernate.tutorial.dto.Vehicle"/>
</session-factory>
</hibernate-configuration>
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
import com.sdnext.hibernate.tutorial.dto.Vehicle;
Now how can implement this mapping through mapping file( .hbm.xml) instead of the annotations.
For user class..
UserDetails.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.sdnext.hibernate.tutorial.dto.UserDetails" table="USER">
<id name="userId" type="long" column="ID" >
<generator class="assigned"/>
</id>
<property name="userName">
<column name="UserName" />
</property>
<list name="vehicle" table="STUDENT_VEHICLE" cascade="all">
<key column="USER_ID" />
<many-to-many column="VEHICLE_ID"
unique="true" class="com.sdnext.hibernate.tutorial.dto.Vehicle" />
</list>
</class>
</hibernate-mapping>
So it is brief description about the One To Many Mapping with using annotation and also
using .hbm.xml files for entity class.
Many-to-One Relationships:
A many-to-one relationship is where one entity contains values that refer to another entity (a column or
set of columns) that has unique values. In relational databases, these many-to-one relationships are often
enforced by foreign key/primary key relationships, and the relationships typically are between fact and
dimension tables and between levels in a hierarchy.
In this example multiple vehicles (BMW Car, AUDI Car, Maruti Car and Mahindra etc.) are linked to the
same User (whose primary key is 1).
According to the relationship many vehicles can have the same owner.
To create this relationship you need to have a USER and VEHICLE table. The relational model is shown
below.
Now we look the following Example related to the One to Many mapping.
UserDetails.java
package com.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table (name="USER")
public class UserDetails
{
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
@Column(name="USER_NAME")
private String userName;
public int getUserId() {
return userId;
}
hibernate.cfg.xml:
<?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">
<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/hibernateDB</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails"/>
<mapping class="com.sdnext.hibernate.tutorial.dto.Vehicle"/>
</session-factory>
</hibernate-configuration>
HibernateTestDemo.java
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.UserDetails;
import com.sdnext.hibernate.tutorial.dto.Vehicle;
public class HibernateTestDemo {
/**
* @param args
*/
public static void main(String[] args)
{
UserDetails user = new UserDetails(); //create an user entity
Vehicle vehicle = new Vehicle(); //create a vehicle entity
Vehicle vehicle2 = new Vehicle(); //create second vehicle entity
vehicle.setVehicleName("BMW Car"); //set BMW car
vehicle.setUser(user); //set user for that car
vehicle2.setVehicleName("AUDI Car"); //set second car Audi
vehicle2.setUser(user);//set user for that car
user.setUserName("Dinesh Rajput"); //set user property
SessionFactory sessionFactory = new
AnnotationConfiguration().configure().buildSessionFactory(); //create the session factory object
Session session = sessionFactory.openSession(); //create the session object
session.beginTransaction(); //create the transaction object
session.save(vehicle);
session.save(vehicle2);
session.save(user);
session.getTransaction().commit();
session.close();
}
}
******************************************************************************
OUTPUT:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
Now how can implement this mapping through mapping file( .hbm.xml) instead of the annotations.
For user class..
UserDetails.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.sdnext.hibernate.tutorial.dto.UserDetails" table="USER">
<id name="userId" type="long" column="ID" >
<generator class="assigned"/>
</id>
<property name="userName">
<column name="UserName" />
</property>
</class>
</hibernate-mapping>
The many-to-one element is used to create the many-to-one relationship between the Vehicle and
UserDetail entities. The cascadeoption is used to cascade the required operations to the associated
entity. If the cascade option is set to all then all the operations will be cascaded. For instance when you
save a Vehicle object, the associated UserDetail object will also be saved automatically.
According to the relationship a user can have in any number of vehicles and the vehicle can have any
number of users.
UserDetail.java
view plainprint?
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.
43.
44.
45.
46.
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.ManyToMany;
javax.persistence.Table;
<b>@Entity
@Table (name="USER")</b>
public class UserDetails
{
<b>@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.AUTO)</b>
private int
userId;
<b>@Column(name="USER_NAME") </b>
private String userName;
<b>@ManyToMany</b>
private Collection<Vehicle> vehicle = new ArrayList<Vehicle>();
public int getUserId() {
return userId;
}
public Collection<Vehicle> getVehicle() {
return vehicle;
}
public void setVehicle(Collection<Vehicle> vehicle) {
this.vehicle = vehicle;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
47.
}</span>
Vehicle.java
view plainprint?
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.
43.
44.
45.
46.
47.
<b>@Entity
@Table(name="VEHICLE")</b>
public class Vehicle
{<b>
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="VEHICLE_ID")</b>
private int vehicleId;
<b>@Column(name="VEHICLE_NAME")</b>
private String vehicleName;
<b>@ManyToMany(mappedBy="vehicle")</b>
private Collection<UserDetails> user = new ArrayList<UserDetails>();
public Collection<UserDetails> getUser() {
return user;
}
public void setUser(Collection<UserDetails> user) {
this.user = user;
}
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
public void setVehicleName(String vehicleName) {
this.vehicleName = vehicleName;
}
}</span>
hibernate.cfg.xml:
view plainprint?
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.ManyToMany;
javax.persistence.Table;
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</propert
y>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB
</property>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvid
er</property>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">create</property>
26.
27.
28.
<mapping class="com.sdnext.hibernate.tutorial.dto.UserDetails">
29.
<mapping class="com.sdnext.hibernate.tutorial.dto.Vehicle">
30.
31.
</mapping></mapping></session-factory>
32.
</hibernate-configuration>
HibernateTestDemo.java
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
Vehicle vehicle2 = new Vehicle();
23.
24.
vehicle.setVehicleName("Car");
25.
vehicle.getUser().add(user);
26.
vehicle.getUser().add(user2);
27.
28.
vehicle2.setVehicleName("Jeep");
29.
vehicle2.getUser().add(user2);
30.
vehicle2.getUser().add(user);
31.
32.
user.setUserName("First User");
33.
user2.setUserName("Second User");
34.
user.getVehicle().add(vehicle);
35.
user.getVehicle().add(vehicle2);
36.
user2.getVehicle().add(vehicle);
37.
user2.getVehicle().add(vehicle2);
38.
39.
SessionFactory sessionFactory = new AnnotationConfiguration().configure(
).buildSessionFactory();
40.
Session session = sessionFactory.openSession();
41.
session.beginTransaction();
42.
session.save(vehicle);
43.
session.save(vehicle2);
44.
session.save(user);
45.
session.save(user2);
46.
session.getTransaction().commit();
47.
session.close();
48.
}
49.
}</b></span>
1.
<hibernate-mapping>
2.
<class name="com.sdnext.hibernate.tutorial.dto.UserDetails" table="USER">
3.
<id column="ID" name="userId" type="long">
4.
<generator class="assigned">
5.
</generator></id>
6.
<property column="column" name="UserName">
7.
<list cascade="all" name="vehicle" table="USER_VEHICLE">
8.
<key column="USER_ID">
9.
<many-tomany class="com.sdnext.hibernate.tutorial.dto.Vehicle" column="VEHICLE_ID">
10.
</many-to-many></key></list>
11.
</property></class>
12.
</hibernate-mapping>
vehicle.hbm.xml
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
<hibernate-mapping>
<class name="com.sdnext.hibernate.tutorial.dto.Vehicle" table="VEHICLE">
<id column="ID" name="userId" type="long">
<generator class="assigned">
</generator></id>
<property column="VEHICLE_NAME" name="vehicleName">
</property></class>
</hibernate-mapping>
JPA Relationship
In this section, you will know about the jpa relationship. JPA supports the relationship between entities.
There are following types of relationship:
1.
One-to-one
2.
One-to-many
3.
Many-to-one
4.
Many-to-many
JPA relationships are not bi-directional. JPA annotations are added to define the relationship. If, you want
to make a relationship bi-directional to use a special attribute.
1.
One-to-one: A OneToOne relation mapping to a single-value association to another
entity. It has one-to-one multiplicity and infers the associated target entity from the type of the
object being referenced.
Use of the @OneToOne Annotation:
1.
Configure the fetch type to LAZY
2.
Configure the mapping to forbid null values (for non-primitive types) in case null
values are inappropriate for your application
3.
Configure the associated target entity if it cannot be inferred from the type of the
object being referenced
4.
Configure the operations that must be cascaded to the target of the association.
For example, if the owning entity is removed, ensure that the target of the association is
also removed
2.
One-to-many: JPA defines a OneToMany mapping for a many-valued association with
one-to-many multiplicity.
Use of the @OneToMany Annotation:
1.
Configure the fetch type to EAGER
2.
Configure the associated target entity because the Collection used is not defined
using generics
3.
Configure the operations that must be cascaded to the target of the association:
for example, if the owning entity is removed, ensure that the target of the association is
also removed
4.
Configure the details of the join table used by TopLink JPA for uni-directional
one-to-many relationships
3.
Many-to-one: JPA defines a ManyToOne mapping for a single-valued association to
another entity class that has many-to-one multiplicity.
Use the @ManyToOne Annotation to:
1.
Configure the fetch type to LAZY
2.
Configure the mapping to forbid null values (for non-primitive types) in case null
values are inappropriate for your application
3.
Configure the associated target entity if it cannot be inferred from the type of the
object being referenced
4.
Configure the operations that must be cascaded to the target of the association:
for example, if the owning entity is removed, ensure that the target of the association is
also removed
4.
Many-to-many: JPA defines a @ManyToMany mapping for a many-valued association
with many-to-many multiplicity.
Use of the @ManyToMany annotation:
1.
Declare the cardinality of the relationship
2.
Configure the fetch type to EAGER
3.
Configure the mapping to forbid null values (for non-primitive types) in case null
values are inappropriate for your application
4.
Configure the associated target entity because the Collection used is not defined
using generics
5.
Configure the operations that must be cascaded to the target of the association;
for example, if the owning entity is removed, ensure that the target of the association is
also removed
There are following types of cascade:
6.
CascadeType.PERSIST: When we persist and entity all the entities held in this
field persist too. If you want to persist an entity and the fields dont use it fails.
7.
CascadeType.REMOVE: When we delete an entity all the entities held in this
field delete too.
8.
CascadeType.REFRESH: When we refresh an entity all the entities held in this
field refresh too.
9.
CascadeType.MERGE: When we merde an entity all the entities held in this flied
merged too
The property cascade = CascadeType.ALL indicates that when we persist, remove, refresh or merge
this entity all the entities held in this field would be persist, remove, delete or update.
Inheritance is one of the most visible facets of Object-relational mismatch. Object oriented systems can model
both is a and has a relationship. Relational model supports only has a relationship between two entities.
Hibernate can help you map such Objects with relational tables. But you need to choose certain mapping strategy
based on your needs. There are three possible strategies to use.
1.
2.
3.
Simplest to implement.
Performance wise better than all strategies because no joins or sub-selects need to be
performed.
Disadvantages:
Most of the column of table are nullable so the NOT NULL constraint cannot be applied.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
gy
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
package com.sdnext.hibernate.tutorial.dto;
import
import
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.Inheritance;
javax.persistence.InheritanceType;
javax.persistence.Table;
@Entity
@Table(name="VEHICLE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) //Least normalisation strate
public class Vehicle
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="VEHICLE_ID")
private int vehicleId;
@Column(name="VEHICLE_NAME")
private String vehicleName;
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
34.
35.
36.
37.
TwoWheeler.java
view plainprint?
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.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="TWO_WHEELER")
//@DiscriminatorValue("Bike")
public class TwoWheeler extends Vehicle
{
@Column(name="STEERING_TYPE")
private String steeringTwoWheeler;
public String getSteeringTwoWheeler()
{
return steeringTwoWheeler;
}
public void setSteeringTwoWheeler(String steeringTwoWheeler)
{
this.steeringTwoWheeler = steeringTwoWheeler;
}
}
FourWheeler.java
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
package com.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name="FOUR_WHEELER")
//@DiscriminatorValue("Car")
public class FourWheeler extends Vehicle
{
@Column(name="STEERING_TYPE")
private String steeringFourWheeler;
public String getSteeringFourWheeler()
{
return steeringFourWheeler;
}
public void setSteeringFourWheeler(String steeringFourWheeler)
{
this.steeringFourWheeler = steeringFourWheeler;
23.
24.
}
}
hibernate.cfg.xml
view plainprint?
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/vehicleDB2</prope
rty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</pr
operty>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">create</property>
26.
27.
28.
<mapping class="com.sdnext.hibernate.tutorial.dto.Vehicle">
29.
<mapping class="com.sdnext.hibernate.tutorial.dto.TwoWheeler">
30.
<mapping class="com.sdnext.hibernate.tutorial.dto.FourWheeler">
31.
32.
</mapping></mapping></mapping></session-factory>
33.
</hibernate-configuration>
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.FourWheeler;
import com.sdnext.hibernate.tutorial.dto.TwoWheeler;
import com.sdnext.hibernate.tutorial.dto.Vehicle;
public class HibernateTestDemo {
/**
14.
* @param args
15.
*/
16.
public static void main(String[] args)
17.
{
18.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
19.
Session session = sessionFactory.openSession();
20.
session.beginTransaction();
21.
22.
Vehicle vehicle = new Vehicle();
23.
vehicle.setVehicleName("Car");
24.
25.
TwoWheeler twoWheeler = new TwoWheeler();
26.
twoWheeler.setVehicleName("Bike");
27.
twoWheeler.setSteeringTwoWheeler("Bike Steering Handle");
28.
29.
FourWheeler fourWheeler = new FourWheeler();
30.
fourWheeler.setVehicleName("Alto");
31.
fourWheeler.setSteeringFourWheeler("Alto Steering Wheel");
32.
33.
session.save(vehicle);
34.
session.save(twoWheeler);
35.
session.save(fourWheeler);
36.
37.
session.getTransaction().commit();
38.
session.close();
39.
}
40.
}
In the above table Vehicle there are four columns (DTYPE, VEHICLE_ID, VEHICLE_NAME,
STEERING_TYPE).
The first column has the value of discriminator type(DTYPE) is Vehicle, TwoWheeler, FourWheeler as
its entity name by default.
For user convenience we can override the default value of column as well as column name by using the
following annotation.
@DiscriminatorColumn
Target:
Classes
Specifies the discriminator column for the SINGLE_TABLE and JOINED Inheritance mapping strategies.
The strategy and the discriminator column are only specified in the root of an entity class hierarchy or
subhierarchy in which a different inheritance strategy is applied
If the DiscriminatorColumn annotation is missing, and a discriminator column is required, the name of the
discriminator column defaults to "DTYPE" and the discriminator type to DiscriminatorType.STRING.
@DiscriminatorValue
Target:
Classes
Specifies the value of the discriminator column for entities of the given type.
The DiscriminatorValue annotation can only be specified on a concrete entity class.
If the DiscriminatorValue annotation is not specified and a discriminator column is used, a providerspecific function will be used to generate a value representing the entity type. If the DiscriminatorType is
STRING, the discriminator value default is the entity name.
The inheritance strategy and the discriminator column are only specified in the root of an entity class
hierarchy or subhierarchy in which a different inheritance strategy is applied. The discriminator value, if
not defaulted, should be specified for each entity class in the hierarchy.
@Inheritance
Target:
Classes
Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class
that is the root of the entity class hierarchy. If the Inheritance annotation is not specified or if no
inheritance type is specified for an entity class hierarchy, the SINGLE_TABLE mapping strategy is used.
Now adding the following annotation to the Vehicle class is
view plainprint?
1.
2.
3.
gy
4.
5.
6.
7.
8.
9.
@Entity
@Table(name="VEHICLE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) //Least normalisation strate
@DiscriminatorColumn(
name="VEHICLE_TYPE",
discriminatorType=DiscriminatorType.STRING
)
public class Vehicle
{
1.
2.
3.
@DiscriminatorValue("Bike")
public class TwoWheeler extends Vehicle
{
1.
2.
3.
@DiscriminatorValue("Car")
public class FourWheeler extends Vehicle
{
After these above modification we run the code then we will get the following output.
Disadvantage:
To support polymorphism either container has to do multiple trips to database or use SQL UNION
kind of feature.
In this case there no need for the discriminator column because all entity has own table.
The Vehicle entity in this case is
Vehicle.java
view plainprint?
1.
2.
3.
4.
5.
package com.sdnext.hibernate.tutorial.dto;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
d
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
import
import
import
import
import
import
import
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.Inheritance;
javax.persistence.InheritanceType;
javax.persistence.Table;
@Entity
@Table(name="VEHICLE")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) //slightly more normalize
public class Vehicle
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="VEHICLE_ID")
private int vehicleId;
@Column(name="VEHICLE_NAME")
private String vehicleName;
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
public void setVehicleName(String vehicleName) {
this.vehicleName = vehicleName;
}
}
And there no need to the discriminator value for the TwoWheeler and FourWheeler Entity so in this case
the
TwoWheeler.java
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
package com.sdnext.hibernate.tutorial.dto;
import
import
import
import
javax.persistence.Column;
javax.persistence.DiscriminatorValue;
javax.persistence.Entity;
javax.persistence.Table;
@Entity
@Table(name="TWO_WHEELER")
public class TwoWheeler extends Vehicle
{
@Column(name="STEERING_TYPE")
private String steeringTwoWheeler;
public String getSteeringTwoWheeler()
{
return steeringTwoWheeler;
}
public void setSteeringTwoWheeler(String steeringTwoWheeler)
21.
22.
23.
24.
{
this.steeringTwoWheeler = steeringTwoWheeler;
}
}
FourWheeler.java
view plainprint?
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.sdnext.hibernate.tutorial.dto;
import
import
import
import
javax.persistence.Column;
javax.persistence.DiscriminatorValue;
javax.persistence.Entity;
javax.persistence.Table;
@Entity
@Table(name="FOUR_WHEELER")
public class FourWheeler extends Vehicle
{
@Column(name="STEERING_TYPE")
private String steeringFourWheeler;
public String getSteeringFourWheeler()
{
return steeringFourWheeler;
}
public void setSteeringFourWheeler(String steeringFourWheeler)
{
this.steeringFourWheeler = steeringFourWheeler;
}
}
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.
package com.sdnext.hibernate.tutorial.dto;
import
import
import
import
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.DiscriminatorColumn;
javax.persistence.DiscriminatorType;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.Inheritance;
javax.persistence.InheritanceType;
javax.persistence.Table;
@Entity
@Table(name="VEHICLE")
@Inheritance(strategy=InheritanceType.JOINED)//Highly normalized
public class Vehicle
{
@Id
@GeneratedValue
@Column(name="VEHICLE_ID")
private int vehicleId;
@Column(name="VEHICLE_NAME")
private String vehicleName;
public int getVehicleId() {
return vehicleId;
}
public void setVehicleId(int vehicleId) {
this.vehicleId = vehicleId;
}
public String getVehicleName() {
return vehicleName;
}
public void setVehicleName(String vehicleName) {
this.vehicleName = vehicleName;
}
}
Criteria
Single Table
Data not
normalized.
Constraint for
Normalized.
mandatory columns to be
Table Support not nullable cannot
Change in any
subclass leads to change
in structure of Table
Discriminator
Present
Column
Retrieving
data
Absent
Not
maintainable.
Change in
base class leads to
changes in all tables
of derived class
Absent
Mandatory
Optional
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 com.sdnext.hibernate.tutorial.dto;
import java.io.Serializable;
import
import
import
import
javax.persistence.Column;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
@Entity
@Table(name="STUDENT")
public class Student implements Serializable
{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 8633415090390966715L;
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="STUDENT_NAME")
private String studentName;
@Column(name="ROLL_NUMBER")
private int rollNumber;
@Column(name="COURSE")
private String course;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getRollNumber() {
return rollNumber;
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
}
public void setRollNumber(int rollNumber) {
this.rollNumber = rollNumber;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
}
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB2</pro
perty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</pr
operty>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">update</property>
26.
27.
<mapping class="com.sdnext.hibernate.tutorial.dto.Student">
28.
29.
</mapping></session-factory>
30.
</hibernate-configuration>
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
y();
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
package com.sdnext.hibernate.tutorial.utility;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateUtil
{
private static final SessionFactory sessionFactory;
static
{
try
{
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactor
}
catch(Throwable th){
System.err.println("Enitial SessionFactory creation failed"+th);
throw new ExceptionInInitializerError(th);
}
}
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
}
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 com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.sdnext.hibernate.tutorial.dto.Student;
import com.sdnext.hibernate.tutorial.utility.HibernateUtil;
public class CreateStudent {
/**
* @param args
*/
public static void main(String[] args)
{
//Create student entity object
Student student = new Student();
student.setStudentName("Dinesh Rajput");
student.setRollNumber(01);
student.setCourse("MCA");
//Create session factory object
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
//getting session object from session factory
Session session = sessionFactory.openSession();
//getting transaction object from session object
session.beginTransaction();
session.save(student);
System.out.println("Inserted Successfully");
31.
32.
33.
34.
35.
session.getTransaction().commit();
session.close();
sessionFactory.close();
}
}
OUTPUT:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Inserted Successfully
Now the following code the reading the student data from database.
Step 5: Reading the Student data from the database table STUDENT
ReadStudent.java
view plainprint?
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.
package com.sdnext.hibernate.tutorial;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.sdnext.hibernate.tutorial.dto.Student;
import com.sdnext.hibernate.tutorial.utility.HibernateUtil;
public class ReadStudent {
/**
* @param args
*/
public static void main(String[] args)
{
//Create session factory object
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
//getting session object from session factory
Session session = sessionFactory.openSession();
//getting transaction object from session object
session.beginTransaction();
Query query = session.createQuery("from Student");
List<student> students = query.list();
27.
for(Student student : students)
28.
{
29.
System.out.println("Roll Number: "+student.getRollNumber()+", Student Name: "+st
udent.getStudentName()+", Course: "+student.getCourse());
30.
}
31.
session.getTransaction().commit();
32.
sessionFactory.close();
33.
}
34.
}
35.
</student>
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select student0_.ID as ID0_, student0_.COURSE as COURSE0_, student0_.ROLL_NUMBER
as ROLL3_0_, student0_.STUDENT_NAME as STUDENT4_0_ from STUDENT student0_
Roll Number: 1, Student Name: Dinesh Rajput, Course: MCA
Roll Number: 2, Student Name: Anamika Rajput, Course: PGDCP
Roll Number: 3, Student Name: Adesh Rajput, Course: MA
Roll Number: 4, Student Name: Vinesh Rajput, Course: BA
The following code is for updating the data into the database table "STUDENT".
Step 6: Update the Student Record in the Database.
UpdateStudent.java
view plainprint?
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.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.sdnext.hibernate.tutorial.dto.Student;
import com.sdnext.hibernate.tutorial.utility.HibernateUtil;
public class UpdateStudent {
/**
* @param args
*/
public static void main(String[] args)
{
//Create session factory object
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
//getting session object from session factory
Session session = sessionFactory.openSession();
//getting transaction object from session object
session.beginTransaction();
Student student = (Student)session.get(Student.class, 2);
student.setStudentName("Sweety Rajput");
25.
26.
27.
28.
29.
System.out.println("Updated Successfully");
session.getTransaction().commit();
sessionFactory.close();
}
}
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select student0_.ID as ID0_0_, student0_.COURSE as COURSE0_0_,
student0_.ROLL_NUMBER as ROLL3_0_0_, student0_.STUDENT_NAME as STUDENT4_0_0_ from
STUDENT student0_ where student0_.ID=?
Hibernate: update STUDENT set COURSE=?, ROLL_NUMBER=?, STUDENT_NAME=? where ID=?
Updated Successfully
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.sdnext.hibernate.tutorial.dto.Student;
import com.sdnext.hibernate.tutorial.utility.HibernateUtil;
public class DeleteStudent {
/**
* @param args
*/
public static void main(String[] args)
{
//Create session factory object
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
//getting session object from session factory
Session session = sessionFactory.openSession();
//getting transaction object from session object
session.beginTransaction();
22.
23.
24.
25.
26.
27.
28.
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select student0_.ID as ID0_0_, student0_.COURSE as COURSE0_0_,
student0_.ROLL_NUMBER as ROLL3_0_0_, student0_.STUDENT_NAME as STUDENT4_0_0_ from
STUDENT student0_ where student0_.ID=?
Deleted Successfully
Hibernate: delete from STUDENT where ID=?
1. Transient State:
A New instance of a persistent class which is not associated with a Session, has no representation in
the database and no identifier value is considered transient by Hibernate:
view plainprint?
1.
2.
3.
2. Persistent State:
A persistent instance has a representation in the database , an identifier value and is associated with
a Session. You can make a transient instance persistent by associating it with a Session:
view plainprint?
1.
2.
3. Detached State:
Now, if we close the Hibernate Session, the persistent instance will become a detached instance: it
isn't attached to aSession anymore (but can still be modified and reattached to a new Session later
though).
view plainprint?
1.
2.
session.close();
//user in detached state
1.
package com.sdnext.hibernate.tutorial;
2.
3.
import org.hibernate.Session;
4.
import org.hibernate.SessionFactory;
5.
import org.hibernate.cfg.AnnotationConfiguration;
6.
7.
import com.sdnext.hibernate.tutorial.dto.UserDetails;
8.
9.
public class HibernateTestDemo {
10.
/**
11.
* @param args
12.
*/
13.
public static void main(String[] args)
14.
{
15.
UserDetails userDetails = new UserDetails();
16.
userDetails.setUserName("Dinesh Rajput");
17.
userDetails.setAddress("Noida City");
18.
//Here 'userDetails' is TRANSIENT object
19.
20.
SessionFactory sessionFactory = new AnnotationConfiguration().co
nfigure().buildSessionFactory();
21.
Session session = sessionFactory.openSession();
22.
session.beginTransaction();
23.
24.
session.save(userDetails);
25.
//Here 'userDetails' is PERSISTENT object
26.
userDetails.setUserName("User Updated after session close");
27.
28.
session.getTransaction().commit();
29.
30.
31.
32.
session.close();
//Here 'userDetails' is DETACHED object
}
}
Here we see when create an object it is in transient state in this state hibernate does not ask for save
this object means that in this state hibernate's session does not associate with that object in this state.
Once we calling session's save method now object move to the persistent state i.e. hibernate's session
associated with that object in this state if any change made in the object hibernate ask to the database
and made change in the database also.
After done our required events when we calling session's close method then object moves in
the detached state.
Here we see that we are not getting new object from new operator, we get the object from session's get
method. Here we pass a primary key in the get method and getting a persistent object.
Here after getting persistent object from session of hibernate. When we are calling the delete method of
the session object moves from persistent state to the transient state. If we calling the close method of the
session then that object moves to the detached state. If once object move to the transient state it never
become a persistent object.
Now we look the states diagram of the entity object in the following.
Lets see in the following example how to an object moves from detached state to the persistent state
again.
HibernateTestDemo.java
view plainprint?
1.
2.
3.
4.
5.
package com.sdnext.hibernate.tutorial;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
6.
7.
import com.sdnext.hibernate.tutorial.dto.UserDetails;
8.
9.
public class HibernateTestDemo {
10.
11.
/**
12.
* @param args
13.
*/
14.
public static void main(String[] args)
15.
{
16.
UserDetails userDetails = new UserDetails();
17.
//Here 'userDetails' is in TRANSIENT state
18.
19.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
20.
Session session = sessionFactory.openSession();
21.
session.beginTransaction();
22.
23.
userDetails = (UserDetails) session.get(UserDetails.class, 1);
24.
//Here 'userDetails' is in PERSISTENT state
25.
26.
session.save(userDetails);
27.
session.getTransaction().commit();
28.
session.close();
29.
30.
session = sessionFactory.openSession();
31.
session.beginTransaction();
32.
33.
userDetails.setUserName("User Updated after session close");
34.
//Here 'userDetails' is in DETACHED state
35.
36.
session.update(userDetails);
37.
//Here 'userDetails' is again in PERSISTENT state
38.
session.getTransaction().commit();
39.
session.close();
40.
}
41.
}
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.ADDRESS as ADDRESS0_0_,
userdetail0_.USER_NAME as USER3_0_0_ from User_Details userdetail0_ where
userdetail0_.USER_ID=?
Hibernate: select userdetail_.USER_ID, userdetail_.ADDRESS as ADDRESS0_,
userdetail_.USER_NAME as USER3_0_ from User_Details userdetail_ where userdetail_.USER_ID=?
Hibernate: update User_Details set ADDRESS=?, USER_NAME=? where USER_ID=?
Query By Criteria (QBC) and Query BY Example (QBE) using Criteria API
HQL allows representing SQL queries in object-oriented termsby using objects and properties
of objects.
Instead of returning plain data, HQL queries return the query result(s) in the form of
object(s)/tuples of object(s) that are ready to be accessed, operated upon, and manipulated
programmatically. This approach does away with the routine task of creating and populating objects from
scratch with the "resultset" retrieved from database queried.
HQL fully supports polymorphic queries. That is, along with the object to be returned as a query
result, all child objects (objects of subclasses) of the given object shall be returned.
HQL is easy to learn and implement, as its syntax and features are very similar to SQL.
HQL contains many advance features such as pagination, fetch join with dynamic profiling, and
so forth, as compared to SQL.
HQL facilitates writing database-type independent queries that are converted to the native SQL
dialect of the underlying database at runtime. This approach helps tap the extra features the native SQL
query provides, without using a non-standard native SQL query.
HQL Syntax>>
As described earlier, most of HQL's syntax and features are very similar to SQL. An HQL query may
consist of following elements:
Clauses
Aggregate functions
Subqueries
Clauses in the HQL are:
from
select
where
order by
group by
Aggregate functions are:
count(*)
Claus Description
e
Syntax
select [object.]property
Example
select user.userName
from UserDetails as
user
Will return all values
of userName in all
instances
ofUserDetails.
from UserDetails as
user where
user.userId > 2
Will return all
instances of user in
UserDetails whose
correspondinguser.us
erId values are
greater than 2.
order
from UserDetails as
by object0.property0[asc|desc][, object1.prop user order by userId
erty0]...
asc
By default, order is ascending unless specified Will return a list of all
instances of user in
otherwise.
ascending order of
corresponding userId
values.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
package com.sdnext.hibernate.tutorial.dto;
import java.io.Serializable;
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.Table;
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.
@Entity
@Table(name="STUDENT")
public class Student implements Serializable
{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 8633415090390966715L;
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="STUDENT_NAME")
private String studentName;
@Column(name="ROLL_NUMBER")
private int rollNumber;
@Column(name="COURSE")
private String course;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getRollNumber() {
return rollNumber;
}
public void setRollNumber(int rollNumber) {
this.rollNumber = rollNumber;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String toString()
{
return "ROLL Number: "+rollNumber+"| Name: "+studentName+"| Course: "+course;
57.
58.
}
}
hibernate.cfg.xml
view plainprint?
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB2</pro
perty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</pr
operty>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">update</property>
26.
27.
28.
<mapping class="com.sdnext.hibernate.tutorial.dto.Student">
29.
30.
</mapping></session-factory>
31.
</hibernate-configuration>
HibernateTestDemo.java
view plainprint?
1.
package com.sdnext.hibernate.tutorial;
2.
3.
import java.util.List;
4.
5.
import org.hibernate.Query;
6.
import org.hibernate.Session;
7.
import org.hibernate.SessionFactory;
8.
import org.hibernate.cfg.AnnotationConfiguration;
9.
10.
import com.sdnext.hibernate.tutorial.dto.Student;
11.
12.
public class HibernateTestDemo {
13.
/**
14.
* @param args
15.
*/
16.
public static void main(String[] args)
17.
{
18.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
19.
Session session = sessionFactory.openSession();
20.
session.beginTransaction();
21.
22.
String SQL_QUERY = "FROM Student student";
23.
Query query = session.createQuery(SQL_QUERY);
24.
query.setFirstResult(1);//set first result start value
25.
query.setMaxResults(5);//number of result to be display
26.
27.
List<student> students = query.list();
28.
for(Student student : students)
29.
{
30.
System.out.println(student);
31.
}
32.
session.getTransaction().commit();
33.
34.
35.
36.
session.close();
}
}
</student>
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select student0_.ID as ID0_, student0_.COURSE as COURSE0_, student0_.ROLL_NUMBER
as ROLL3_0_, student0_.STUDENT_NAME as STUDENT4_0_ from STUDENT student0_ limit ?, ?
ROLL Number: 2| Name: Sweety Rajput| Course: PGDCP
ROLL Number: 3| Name: Adesh Rajput| Course: MA
ROLL Number: 4| Name: DEV| Course: MA
ROLL Number: 5| Name: RAJ| Course: BA
ROLL Number: 6| Name: Pradeep| Course: BA
SQL INJECTION:
Injecting the value to the SQL statement. SQL injection refers to the act of someone inserting a MySQL statement
to be run on your database without your knowledge. Injection usually occurs when you ask a user for input, like
their name, and instead of a name they give you a MySQL statement that you will unknowingly run on your
database.
Normal: " SELECT * FROM student WHERE studentName= 'sweety'"
Injection: "SELECT * FROM student WHERE studentName= '' +studentName
PARAMETER BINDING:
A bind variable is a named placeholder (preceded by a colon) that is embedded in the query string in place of a
literal. The actual value is substituted at runtime using the setParameter() method.
Without parameter binding, you have to concatenate the parameter String like this (bad code) :
view plainprint?
1.
"'";
2.
3.
Pass an unchecked value from user input to the database will raise security concern, because it can easy get hack
by SQL injection. You have to avoid the above bad code and using parameter binding instead.
2.
Example 1 setParameter
The setParameter is smart enough to discover the parameter data type for you.
view plainprint?
1.
2.
3.
4.
Example 2 setString
You can use setString to tell Hibernate this parameter date type is String.
view plainprint?
1.
2.
3.
4.
Example 3 setProperties
This feature is great ! You can pass an object into the parameter binding. Hibernate will automatic check the
objects properties and match with the colon parameter.
view plainprint?
1.
2.
3.
4.
5.
6.
2. Positional parameters
Its use question mark (?) to define a named parameter, and you have to set your parameter according to the
position sequence. See example
view plainprint?
1.
String hql = "from Student student where student.course= ? and student.studentNa
me = ?";
2.
Query query = session.createQuery(hql);
3.
query.setString(0, "MCA");
4.
query.setParameter(1, "Dinesh Rajput")
5.
List result = query.list();
In Hibernate parameter binding, i would recommend always go for "Named parameters", as its more easy
to maintain, and the compiled SQL statement can be reuse (if only bind parameters change) to increase
the performance.
Named Query is very useful concept in hibernate. It lets you separate queries from coding section of the
application to themapping xml file(.hbm files). The query is given unique name for the entire
application. The application can use the query by using the name of the query. This way the application is
able to use the same query multiple times without writing the same query multiple times.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
<hibernate-mapping>
<class name="com.sdnext.hibernate.tutorial.dto.Student" table="STUDENT">
<id column="ID" name="id" type="int">
<generator class="increment">
</generator></id>
<property name="rollNumber" type="int">
<column name="ROLL_NUMBER">
</column></property>
<property name="studentName" type="String">
<column name="STUDENT_NAME"></column>
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
</property>
<property name="course" type="String">
<column name="COURSE"></column>
</property>
</class>
<sql-query name="findStudentByRollNumber">
<return alias="student" class="com.sdnext.hibernate.tutorial.dto.Student">
<!--[CDATA[
select * from Student student where student.rollNumber = :rollNumber
]]-->
</return>
</sql-query>
</hibernate-mapping>
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
<hibernate-mapping>
<class name="com.sdnext.hibernate.tutorial.dto.Student" table="STUDENT">
<id column="ID" name="id" type="int">
<generator class="increment">
</generator></id>
<property name="rollNumber" type="int">
<column name="ROLL_NUMBER">
</column></property>
<property name="studentName" type="String">
<column name="STUDENT_NAME"></column>
</property>
<property name="course" type="String">
<column name="COURSE"></column>
</property>
</class>
<query name="findStudentByRollNumber">
<!--[CDATA[
from Student student where student.rollNumber = :rollNumber
]]-->
</query>
</hibernate-mapping>
You can place a named query inside hibernate-mapping element, but do not put before
the class element, Hibernate will prompt invalid mapping file, all your named queries have to put after
the class element.
hibernate.cfg.xml
view plainprint?
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB2</pro
perty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</pr
operty>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">update</property>
26.
27.
28.
<mapping resource="student.hbm.xml">
29.
30.
</mapping></session-factory>
31.
</hibernate-configuration>
32.
HibernateTestDemo.java
view plainprint?
1.
package com.sdnext.hibernate.tutorial;
2.
3.
import java.util.List;
4.
5.
import org.hibernate.Query;
6.
import org.hibernate.Session;
7.
import org.hibernate.SessionFactory;
8.
import org.hibernate.cfg.Configuration;
9.
10.
import com.sdnext.hibernate.tutorial.dto.Student;
11.
12.
public class HibernateTestDemo {
13.
/**
14.
* @param args
15.
*/
16.
public static void main(String[] args)
17.
{
18.
SessionFactory sessionFactory = new Configuration().configure().buildSessionFa
ctory();
19.
Session session = sessionFactory.openSession();
20.
session.beginTransaction();
21.
22.
Query query = session.getNamedQuery("findStudentByRollNumber").setInteger("rol
lNumber", 3);
23.
24.
List<student> students = query.list();
25.
for(Student student : students)
26.
{
27.
System.out.println(student);
28.
}
29.
session.getTransaction().commit();
30.
session.close();
31.
}
32.
33.
}
</student>
2. Annotation:
HQL in annotation
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
@NamedQueries({
@NamedQuery(
name = "findStudentByRollNumber",
query = "from Student student where student.rollNumber = :rollNumber"
)
})
@Entity
@Table(name = "STUDENT")
public class Student implements java.io.Serializable {
...
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
@NamedNativeQueries({
@NamedNativeQuery(
name = "findStudentByRollNumber",
query = "select * from Student student where student.rollNumber = :rollNumbe"
resultClass = Student.class
)
})
@Entity
@Table(name = "STUDENT")
public class Student implements java.io.Serializable {
...
In native SQL, you have to declare the resultClass to let Hibernate know what is the return type, failed to
do it will caused the exception "org.hibernate.cfg.NotYetImplementedException: Pure native scalar
queries are not yet supported".
Example:
Student.java
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
package com.sdnext.hibernate.tutorial.dto;
import java.io.Serializable;
import
import
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.NamedQueries;
javax.persistence.NamedQuery;
javax.persistence.Table;
@NamedQueries({
@NamedQuery(
name = "findStudentByRollNumber",
query = "from Student student where student.rollNumber = :rollNumber"
)
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.
63.
64.
})
@Entity
@Table(name="STUDENT")
public class Student implements Serializable
{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 8633415090390966715L;
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="STUDENT_NAME")
private String studentName;
@Column(name="ROLL_NUMBER")
private int rollNumber;
@Column(name="COURSE")
private String course;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getRollNumber() {
return rollNumber;
}
public void setRollNumber(int rollNumber) {
this.rollNumber = rollNumber;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String toString()
{
return "ROLL Number: "+rollNumber+"| Name: "+studentName+"| Course: "+course;
65.
66.
}
}
hibernate.cfg.xml
view plainprint?
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB2</pro
perty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</pr
operty>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">update</property>
26.
27.
28.
<mapping class="com.sdnext.hibernate.tutorial.dto.Student">
29.
30.
</mapping></session-factory>
31.
</hibernate-configuration>
HibernateTestDemo.java
view plainprint?
1.
package com.sdnext.hibernate.tutorial;
2.
3.
import java.util.List;
4.
5.
import org.hibernate.Query;
6.
import org.hibernate.Session;
7.
import org.hibernate.SessionFactory;
8.
import org.hibernate.cfg.AnnotationConfiguration;
9.
10.
import com.sdnext.hibernate.tutorial.dto.Student;
11.
12.
public class HibernateTestDemo {
13.
/**
14.
* @param args
15.
*/
16.
public static void main(String[] args)
17.
{
18.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
19.
Session session = sessionFactory.openSession();
20.
session.beginTransaction();
21.
22.
Query query = session.getNamedQuery("findStudentByRollNumber").setInteger("rol
lNumber", 3);
23.
24.
List<student> students = query.list();
25.
for(Student student : students)
26.
{
27.
System.out.println(student);
28.
}
29.
session.getTransaction().commit();
30.
session.close();
31.
32.
33.
}
}
</student>
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select student0_.ID as ID0_, student0_.COURSE as COURSE0_,
student0_.ROLL_NUMBER as ROLL3_0_, student0_.STUDENT_NAME as STUDENT4_0_ from
STUDENT student0_ where student0_.ROLL_NUMBER=?
ROLL Number: 3| Name: Adesh Rajput| Course: MA
1.
2. The Criteria API supports all the comparision operators such as =, <, >, >=,=<, etc in the
supported Expression class eq(), lt(), gt(), le() , ge() respectively.
view plainprint?
1.
2.
3.
4.
5.
1.
2.
1.
2.
1.
2.
3.
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 com.sdnext.hibernate.tutorial.dto;
import java.io.Serializable;
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.Table;
@Entity
@Table(name="STUDENT")
public class Student implements Serializable
{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 8633415090390966715L;
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="STUDENT_NAME")
private String studentName;
@Column(name="ROLL_NUMBER")
private int rollNumber;
@Column(name="COURSE")
private String course;
public int getId() {
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.
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getRollNumber() {
return rollNumber;
}
public void setRollNumber(int rollNumber) {
this.rollNumber = rollNumber;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String toString()
{
return "ROLL Number: "+rollNumber+"| Name: "+studentName+"| Course: "+course;
}
}
hibernate.cfg.xml
view plainprint?
1.
<hibernate-configuration>
2.
<session-factory>
3.
<!-- Database connection settings -->
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB2</pro
perty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
<!-- JDBC connection pool (use the built-in) -->
10.
<property name="connection.pool_size">1</property>
11.
12.
<!-- SQL dialect -->
13.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
14.
15.
<!-- Enable Hibernate's automatic session context management -->
16.
<property name="current_session_context_class">thread</property>
17.
18.
<!-- Disable the second-level cache -->
19.
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</pr
operty>
20.
21.
<!-- Echo all executed SQL to stdout -->
22.
<property name="show_sql">true</property>
23.
24.
<!-- Drop and re-create the database schema on startup -->
25.
<property name="hbm2ddl.auto">update</property>
26.
27.
28.
29.
30.
31.
<mapping class="com.sdnext.hibernate.tutorial.dto.Student">
</mapping></session-factory>
</hibernate-configuration>
HibernateTestDemo.java
view plainprint?
1.
package com.sdnext.hibernate.tutorial;
2.
3.
import java.util.List;
4.
5.
import org.hibernate.Criteria;
6.
import org.hibernate.Session;
7.
import org.hibernate.SessionFactory;
8.
import org.hibernate.cfg.AnnotationConfiguration;
9.
import org.hibernate.criterion.Restrictions;
10.
11.
import com.sdnext.hibernate.tutorial.dto.Student;
12.
13.
14.
public class HibernateTestDemo {
15.
16.
/**
17.
* @param args
18.
*/
19.
public static void main(String[] args)
20.
{
21.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
22.
Session session = sessionFactory.openSession();
23.
session.beginTransaction();
24.
25.
Criteria criteria = session.createCriteria(Student.class);
26.
criteria.add(Restrictions.eq("studentName", "Dinesh Rajput"));
27.
28.
List<student> students = criteria.list();
29.
30.
for(Student student : students)
31.
{
32.
System.out.println(student);
33.
}
34.
session.getTransaction().commit();
35.
session.close();
36.
}
37.
38.
}
39.
</student>
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select this_.ID as ID0_0_, this_.COURSE as COURSE0_0_, this_.ROLL_NUMBER as
ROLL3_0_0_, this_.STUDENT_NAME as STUDENT4_0_0_ from STUDENT this_ where
this_.STUDENT_NAME=?
ROLL Number: 1| Name: Dinesh Rajput| Course: MCA
In the Next Chapter we will discuss more about the Criteria Query with
Restriction.
1.
2.
1.
1.
2.
3.
Restrictions.lt
This is used to apply a "less than" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.gt
This is used to apply a "greater than" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.le
This is used to apply a "less than or equal" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.ge
This is used to apply a "greater than or equal" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.ne
This is used to apply a "not equal" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.in
This is used to apply an "in" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.or
This returns the disjunction of two expressions.
Simple SQL query >>
view plainprint?
1.
1.
Criteria criteria = session.createCriteria(Student.class);
2.
criteria.add(Restrictions.or(Restrictions.gt("rollNumber", 3), Restrictions.eq("
course", "MA"));
3.
List list = criteria.list();
Restrictions.not
This returns the negation of an expression.
Simple SQL query >>
view plainprint?
1.
1.
2.
)));
3.
Restrictions.like
This is used to apply a "like" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.isNull
This is used to apply an "is null" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restrictions.isNotNull
This is used to apply an "is not null" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restriction.between
This is used to apply a "between" constraint to the named property.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
Restriction.allEq
This is used to apply an "equals" constraint to each property in the key set of a Map.
Simple SQL query >>
view plainprint?
1.
1.
2.
3.
4.
5.
6.
One of the primary concerns of mappings between a database and our Java application
is performance. This is the common concern of the all guys who working with hibernate and
spent the more time in ORM tools for performance-enhancing changes to particular queries and
retrievals. Today I want to discuss about some facets of the Hibernate infrastructure that are
implemented to handle certain performance concerns 1.
The first-level cache - Session (Earlier hibernate already provide this level of cache)
2.
The second-level cache -Session-factory-level cache
3.
and the query cache.
The first-level cache: The first level cache type is the session cache. The session cache caches object
within the current session but this is not enough for long level i.e. session factory scope.
The second-level cache: The second-level cache is called 'second-level' because there is already a
cache operating for you in Hibernate for the duration you have a session open. A Hibernate Session is a
transaction-level cache of persistent data. It is possible to configure a SessionFactory-level cache on a
class-by-class and collection-by-collection basis.
second-level cache
-- Across sessions in an Application
-- Across applications (different applications on same servers with same database)
-- Across clusters (different applications on different servers with same database)
NOTE: Be careful Caches are never aware of changes made to the persistent store by another
application i.e. suppose one application deploy one server with using hibernate and get the data from
database and put to the cache for further using purpose but another application deployed another server
which does not using any ORM tool so it does mot know about Cache and direct interacting with
database and may be update data of database. Now data in Cache is invalid.
Hibernate uses first-level cache by default and you have nothing to do to use first-level cache. Let's go
straight to the optional second-level cache. Not all classes benefit from caching, so it's important to be
able to disable the second-level cache.
The 'second-level' cache exists as long as the session factory is alive. The second-level cache holds on
to the 'data' for all properties and associations (and collections if requested) for individual entities that are
marked to be cached.
In hibernate configuration file (hibernate.cfg.xml) we wrote the following line.
For Disabling the second level of cache we have to made following change to hibernate configuration file.
view plainprint?
1.
2.
rty>
For Enabling the second level of cache we have to made following change to hibernate configuration file.
view plainprint?
1.
<!-- Enable the second-level cache -->
2.
<property name="cache.use_second_level_cache">true</property>
3.
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</pr
operty>
1. Cache Strategy using with Annotation as some changes made to the Model class also.
view plainprint?
1.
2.
3.
4.
5.
6.
7.
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Entity
@Table(name="STUDENT")
public class Student implements Serializable
{
....
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
>
11.
12.
13.
<hibernate-mapping>
<class name="Student" table="STUDENT">
This class contains the student detail.
<cache usage="read-only">
<id column="ID" name="id" type="java.lang.Long">
<generator class="native">
</generator></id>
<property column="STUDENT_NAME" name="studentName" type="java.lang.String"
<property column="lCOURSE" name="course" type="java.lang.String">
<property column="ROLL_NUMBER" name="rollNumber" type="java.lang.Long">
</property></property></property></cache></class>
14.
</hibernate-mapping>
CONCURRENCY STRATEGIES:
A concurrency strategy is a mediator which responsible for storing items of data in the cache and
retrieving them from the cache. If you are going to enable a second-level cache, you will have to decide,
for each persistent class and collection, which cache concurrency strategy to use.
1.
Transactional: Use this strategy for read-mostly data where it is critical to prevent stale
data in concurrent transactions,in the rare case of an update.
2.
Read-write: Again use this strategy for read-mostly data where it is critical to prevent
stale data in concurrent transactions,in the rare case of an update.
3.
Nonstrict-read-write: This strategy makes no guarantee of consistency between the
cache and the database. Use this strategy if data hardly ever changes and a small likelihood of
stale data is not of critical concern.
4.
Read-only: A concurrency strategy suitable for data which never changes. Use it for
reference data only.
You have to download one more jar (ehcache-core-2.5.2) and configure with your application as given in
below..
Now look the following example which describe the Second Level Of Cache i.e. Across the sessions.
HibernateTestDemo.java
view plainprint?
1.
package com.sdnext.hibernate.tutorial;
2.
3.
import org.hibernate.Session;
4.
import org.hibernate.SessionFactory;
5.
import org.hibernate.cfg.AnnotationConfiguration;
6.
7.
import com.sdnext.hibernate.tutorial.dto.Student;
8.
9.
10.
public class HibernateTestDemo {
11.
12.
/**
13.
* @param args
14.
*/
15.
public static void main(String[] args)
16.
{
17.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
18.
Session session = sessionFactory.openSession();
19.
session.beginTransaction();
20.
21.
Student student = (Student) session.get(Student.class, 1);
22.
23.
session.getTransaction().commit();
24.
session.close();
25.
26.
Session session2 = sessionFactory.openSession();
27.
session2.beginTransaction();
28.
29.
Student student2 = (Student) session2.get(Student.class, 1);
30.
31.
session2.getTransaction().commit();
32.
session2.close();
33.
}
34.
}
Output:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: select student0_.ID as ID0_0_, student0_.COURSE as COURSE0_0_,
student0_.ROLL_NUMBER as ROLL3_0_0_, student0_.STUDENT_NAME as STUDENT4_0_0_ from
STUDENT student0_ where student0_.ID=?
As we seen the output there is only one query execute but we called get method for same model object
two times i.e. when retrieve the model object first time it cache to the second level cache when we call
second get of second session object for the same model object it does not execute select query again
because hibernate return this model object from the session.
In the Next Chapter we will discuss more about the Query Cacheing in Hibernate.
1.
Query query = session.createQuery("from Student as student where student.id = ?
and student.studentName = ?");
2.
query.setInt(0, Integer.valueOf(1));
3.
query.setString(1, "Dinesh Rajput");
4.
query.setCacheable(true);
5.
List l = query.list();
hibernate.cache.use_second_level_cache=true|false
hibernate.cache.use_query_cache=true|false
The first turns on the second level cache in general and the second turns on the query cache regions. If
the second is set to false, the query and timestamp cache regions are not created or used.
Suppose there is one situation in which you have to insert 1000000 records in to database in a time. So
what to do in this situation...
In Native Solution in the Hibernate
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
{
Student student = new Student(.....);
session.save(student);
}
tx.commit();
session.close();
Because by default, Hibernate will cache all the persisted objects in the session-level cache and
ultimately your application would fall over with an OutOfMemoryException somewhere around the
50,000th row. You can resolve this problem if you are using batch processing with Hibernate.
To use the batch processing feature, first set hibernate.jdbc.batch_size as batch size to a number either
at 20 or 50 depending on object size. This will tell the hibernate container that every X rows to be inserted
as batch. To implement this in your code we would need to do little modification as follows:
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Above code will work fine for the INSERT operation, but if you want to make UPDATE operation then you
can achieve using the following code:
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
int count = 0;
while(studentCursor .next())
{
Student student = (Student) studentCursor.get(0);
student.setName("DEV");
seession.update(student);
if ( ++count % 50 == 0 ) {
session.flush();
session.clear();
}
}
tx.commit();
session.close();
hibernate.cfg.xml
view plainprint?
1.
<hibernate-configuration>
2.
<session-factory>
3.
4.
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
5.
<property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB2</pro
perty>
6.
<property name="connection.username">root</property>
7.
<property name="connection.password">root</property>
8.
9.
10.
<property name="connection.pool_size">1</property>
11.
12.
13.
<property name="hibernate.jdbc.batch_size"> 50 </property>
14.
15.
16.
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
17.
18.
19.
<property name="current_session_context_class">thread</property>
20.
21.
22.
<property name="hibernate.cache.use_second_level_cache">false</property>
23.
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</pr
operty>
24.
25.
26.
<property name="show_sql">true</property>
27.
28.
29.
<property name="hbm2ddl.auto">update</property>
30.
31.
32.
<mapping class="com.sdnext.hibernate.tutorial.dto.Student">
33.
34.
</mapping></session-factory>
35.
</hibernate-configuration>
Student.java
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
package com.sdnext.hibernate.tutorial.dto;
import java.io.Serializable;
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.Table;
@Entity
@Table(name="STUDENT")
public class Student implements Serializable
{
/**
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.
* serialVersionUID
*/
private static final long serialVersionUID = 8633415090390966715L;
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="STUDENT_NAME")
private String studentName;
@Column(name="ROLL_NUMBER")
private int rollNumber;
@Column(name="COURSE")
private String course;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getRollNumber() {
return rollNumber;
}
public void setRollNumber(int rollNumber) {
this.rollNumber = rollNumber;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String toString()
{
return "ROLL Number: "+rollNumber+"| Name: "+studentName+"| Course: "+course;
}
}
HibernateTestDemo.java
view plainprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
package com.sdnext.hibernate.tutorial;
import
import
import
import
org.hibernate.Session;
org.hibernate.SessionFactory;
org.hibernate.Transaction;
org.hibernate.cfg.AnnotationConfiguration;
import com.sdnext.hibernate.tutorial.dto.Student;
16.
public static void main(String[] args)
17.
{
18.
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buil
dSessionFactory();
19.
Session session = sessionFactory.openSession();
20.
Transaction transaction = session.beginTransaction();
21.
22.
for ( int i=0; i<100000; i++ )
23.
{
24.
String studentName = "DINESH " + i;
25.
int rollNumber = 9 + i;
26.
String course = "MCA " + i;
27.
Student student = new Student();
28.
student.setStudentName(studentName);
29.
student.setRollNumber(rollNumber);
30.
student.setCourse(course);
31.
session.save(student);
32.
if( i % 50 == 0 )
33.
{
34.
session.flush();
35.
session.clear();
36.
}
37.
}
38.
transaction.commit();
39.
session.close();
40.
}
41.
42.
}
Output: .................................
..................................
....................................
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
Hibernate: insert into STUDENT (COURSE, ROLL_NUMBER, STUDENT_NAME) values (?, ?, ?)
....................................
.................................
..............................
There are two reasons for batching your hibernate database interactions. The first is to maintain a
reasonable first level cache size so that you do not run out memory. The second is that you want to batch
the inserts and updates so that they are executed efficiently by the database. The example above will
accomplish the first goal but not the second.
view plainprint?
1.
2.
3.
4.
5.
6.
The problem is Hibernate looks at each SQL statement and checks to see if it is the same statement as
the previously executed statement. If they are and if it hasn't reached the batch_size it will batch those
two statements together using JDBC2 batch. However, if your statements look like the example above,
hibernate will see alternating insert statements and will flush an individual insert statement for each
record processed. So 1 million new students would equal a total of 2 million insert statements in this case.
This is extremely bad for performance.