0% found this document useful (0 votes)
48 views48 pages

Hibernate Basics

Hibernate is an open source Java persistence framework that performs object-relational mapping and allows developers to query databases using HQL and SQL. It reduces complexity and defects by handling ORM mappings between Java objects and database tables. The document then provides details on the main components of Hibernate's architecture - configuration, session factory, session, queries, caching, transactions, and persistent objects. It also includes a code sample of a basic "Hello World" Hibernate application demonstrating creating an entity class, configuration files, and performing CRUD operations.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views48 pages

Hibernate Basics

Hibernate is an open source Java persistence framework that performs object-relational mapping and allows developers to query databases using HQL and SQL. It reduces complexity and defects by handling ORM mappings between Java objects and database tables. The document then provides details on the main components of Hibernate's architecture - configuration, session factory, session, queries, caching, transactions, and persistent objects. It also includes a code sample of a basic "Hello World" Hibernate application demonstrating creating an entity class, configuration files, and performing CRUD operations.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

1.

Hibernate Basics:
Hibernate is an open source Java persistence framework project. It performs powerful object-
relational mapping and query databases using HQL and SQL. Hibernate is a great tool for ORM
mappings in Java. It can cut down a lot of complexity and thus defects as well from your
application, which may otherwise find a way to exist. This is specially boon for developers with
limited knowledge of SQL.

The following diagram summarizes the main building blocks in hibernate architecture.

Let’s understand what each block represents.

1. Configuration: Generally written


in hibernate.properties or hibernate.cfg.xml files. For Java configuration, you
may find class annotated with @Configuration. It is used by Session Factory to
work with Java Application and the Database. It represents an entire set of
mappings of an application Java Types to an SQL database.
2. Session Factory: Any user application requests Session Factory for a session object.
Session Factory uses configuration information from above listed files, to
instantiates the session object appropriately.
3. Session: This represents the interaction between the application and the database
at any point of time. This is represented by the org.hibernate.Session class. The
instance of a session can be retrieved from the SessionFactory bean.
4. Query: It allows applications to query the database for one or more stored objects.
Hibernate provides different techniques to query database,
including NamedQuery and Criteria API.
5. First-level cache: It represents the default cache used by Hibernate Session object
while interacting with the database. It is also called as session cache and caches
objects within the current session. All requests from the Session object to the
database must pass through the first-level cache or session cache. One must note
that the first-level cache is available with the session object until the Session object
is live.
6. Transaction: enables you to achieve data consistency, and rollback incase
something goes unexpected.
7. Persistent objects: These are plain old Java objects (POJOs), which get persisted as
one of the rows in the related table in the database by hibernate. They can be
configured in configurations files (hibernate.cfg.xml or hibernate.properties) or
annotated with @Entity annotation.
8. Second-level cache: It is used to store objects across sessions. This needs to be
explicitly enabled and one would be required to provide the cache provider for a
second-level cache. One of the common second-level cache providers is EhCache.

2. Hello World Example: (Go through doc and then


19_Hibernate_Crud_By_Core_Java)
I have created an Employee class and declared four
attributes id, email, firstname and lastname.

I want the id attribute should be generated automatically so that application code does
not store a local cache of employee ids.

So far we targeted what we want to make in our first application. Lets identify the files
need to be created.
1. hibernate.cfg.xml -This configuration file will be used to store database
connection information and schema level settings.
2. EmployeeEntity.java – This class will refer Java POJOs having hibernate
annotations.
3. HibernateUtil.java – This class will have utility methods which will be used for
creating session factory and session objects.
4. TestHibernate.java – This class will be used to test our configuration settings and
Emplyee entity annotations.

Requirement for pom.xml file, For now we will be using only few of them:

➔ pom.xml
<dependency>
<groupid>org.hibernate</groupid>
<artifactid>hibernate-commons-annotations</artifactid>
<version>3.0.0.ga</version>
</dependency>
<dependency>
<groupid>org.hibernate</groupid>
<artifactid>hibernate-annotations</artifactid>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-java</artifactid>
<version>5.1.6</version>
</dependency>
<dependency>
<groupid>antlr</groupid>
<artifactid>antlr</artifactid>
<version>2.7.6</version>
</dependency>
<dependency>
<groupid>commons-collections</groupid>
<artifactid>commons-collections</artifactid>
<version>3.1</version>
</dependency>
<dependency>
<groupid>dom4j</groupid>
<artifactid>dom4j</artifactid>
<version>1.6.1</version>
</dependency>
<dependency>
<groupid>javassist</groupid>
<artifactid>javassist</artifactid>
<version>3.4.GA</version>
</dependency>
<dependency>
<groupid>javax.transaction</groupid>
<artifactid>jta</artifactid>
<version>1.1</version>
</dependency>
<dependency>
<groupid>org.slf4j</groupid>
<artifactid>slf4j-api</artifactid>
<version>1.5.6</version>
</dependency>
<dependency>
<groupid>org.slf4j</groupid>
<artifactid>slf4j-log4j12</artifactid>
<version>1.5.6</version>
</dependency>

➔ 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>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatetest
<property name="hibernate.connection.password">******</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="hibernate.test.dto.EmployeeEntity"></mapping>
</session-factory>
</hibernate-configuration>

hbm2ddl.auto ->

hibernate.hbm2ddl.auto 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.

e.g. validate | update | create | create-drop


So the list of possible options are,

• validate: validate the schema, makes no changes to the database.


• update: update the schema.
• create: creates the schema, destroying previous data.
• create-drop: drop the schema when the SessionFactory is closed explicitly, typically when the
application is stopped.
➔ EmployeeEntity.java
package hibernate.test.dto;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.annotations.OptimisticLockType;

@Entity
@org.hibernate.annotations.Entity(optimisticLock = OptimisticLockType.ALL)
@Table(name = "Employee", uniqueConstraints = {
@UniqueConstraint(columnNames = "ID"),
@UniqueConstraint(columnNames = "EMAIL") })
public class EmployeeEntity implements Serializable {

private static final long serialVersionUID = -1798070786993154676L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer employeeId;

@Column(name = "EMAIL", unique = true, nullable = false, length = 100)


private String email;

@Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)


private String firstName;

@Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)


private String lastName;

// Accessors and mutators for all four fields


}

➔ Hibernate session factory


package hibernate.test;

import java.io.File;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateUtil
{
private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory()


{
try {
// Create the SessionFactory from hibernate.cfg.xml
return new AnnotationConfiguration().configure(
new File("hibernate.cgf.xml")).buildSessionFactory();

} catch (Throwable ex) {


// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {


return sessionFactory;
}

public static void shutdown() {


// Close caches and connection pools
getSessionFactory().close();
}
}

➔ TestHibernate.java
package hibernate.test;

import hibernate.test.dto.EmployeeEntity;
import org.hibernate.Session;

public class TestHibernate {

public static void main(String[] args) {


Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

// Add new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("[email protected]");
emp.setFirstName("demo");
emp.setLastName("user");
session.save(emp);

session.getTransaction().commit();
HibernateUtil.shutdown();
}
}

Above code will create a new table employee in database and insert one row in this table.
In logs you can verify the insert statement which got executed.

➔ Console
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)

3. Hibernate fetch entity– get vs load methods

Hibernate load entity – session.load()

Let’s look at different flavors of load() method available in hibernate session interface.
public class TestHibernate
{
public static void main(String[] args)
{
Session sessionOne = HibernateUtil.getSessionFactory().openSession();
sessionOne.beginTransaction();

// Create new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setFirstName("Rohit");
emp.setLastName("Patil");

//Save employee
sessionOne.save(emp);
//store the employee id generated for future use
Integer empId = emp.getEmployeeId();
sessionOne.getTransaction().commit();

/************************************************************************/

//Let's open a new session to test load() methods


Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
sessionTwo.beginTransaction();

//first load() method example


EmployeeEntity emp1 = (EmployeeEntity) sessionTwo.load(EmployeeEntity.class, empId);
System.out.println(emp1.getFirstName() + " - " +emp1.getLastName());
//Let's verify the entity name
System.out.println(sessionTwo.getEntityName(emp1));

sessionTwo.getTransaction().commit();
}
}

Hibernate get entity by id – session.get()

Code will be same as load() method.

Difference between load() and get() methods

The difference between get and load methods lies in return value when the identifier
does not exist in database.

➔ In case of get() method, we will get return value as NULL if identifier is absent.
But in case of load() method, we will get a runtime exception.

The exception in case of load method will look like this:

Runtime exception in load() method when ID does not exist


Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the
given identifier exists:

➔ Get method never returns a proxy, it either returns null or fully initialized Object,
while load() method may return proxy, which is the object with ID but without
initializing other properties, which is lazily initialized. If you are just using returned
object for creating relationship and only need Id then load() is the way to go.

4. Persist: Hibernate Insert Query Tutorial

In the same example as above, we will use below class to insert data in DB:

public class TestHibernateInsert {

public static void main(String[] args)


{
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

//Add new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setEmail("[email protected]");
emp.setFirstName("rohit");
emp.setLastName("patil");

//Save the employee in database


session.save(emp);

//Commit the transaction


session.getTransaction().commit();
HibernateUtil.shutdown();
}
}

5. Save and SaveOrUpdate:

➔ Below will work fine:


public class SimplestSaveEntityExample
{
public static void main(String[] args)
{
Session sessionOne = HibernateUtil.getSessionFactory().openSession();
sessionOne.beginTransaction();

//Create new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setEmployeeId(1);
emp.setFirstName("Rohit");
emp.setLastName("Patil");

//Save employee
sessionOne.save(emp);

sessionOne.getTransaction().commit();
HibernateUtil.shutdown();
}
}

➔ Below will give error, because other session is used for save:

public class SaveEntityAgainInAnotherSession


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

//Create new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setEmployeeId(1);
emp.setFirstName("Rohit");
emp.setLastName("Patil");
//Save employee
sessionOne.save(emp);
sessionOne.getTransaction().commit();

Session sessionTwo = HibernateUtil.getSessionFactory().openSession();


sessionTwo.beginTransaction();

emp.setLastName("temp");
//Save employee again second time
sessionTwo.save(emp);

sessionTwo.getTransaction().commit();
HibernateUtil.shutdown();
}
}

➔ Below will work perfectly:

public class SaveEntityAgainInSameSession


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

//Create new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setEmployeeId(1);
emp.setFirstName("Rohit");
emp.setLastName("Patil");

//Save employee
sessionOne.save(emp);

emp.setLastName("temp");
//Save employee again second time
sessionOne.save(emp);

sessionOne.getTransaction().commit();
HibernateUtil.shutdown();
}
}

➔ SaveOrUpdate
public class SaveOrUpdateMethodExample
{
public static void main(String[] args)
{
Session sessionOne = HibernateUtil.getSessionFactory().openSession();
sessionOne.beginTransaction();
//Create new Employee object
EmployeeEntity emp = new EmployeeEntity();
emp.setEmployeeId(1);
emp.setFirstName("Rohit");
emp.setLastName("Patil");

//Save employee
sessionOne.save(emp);
sessionOne.getTransaction().commit();

Session sessionTwo = HibernateUtil.getSessionFactory().openSession();


sessionTwo.beginTransaction();

emp.setLastName("temp");
//Save employee again second time
sessionTwo.saveOrUpdate(emp);

sessionTwo.getTransaction().commit();
HibernateUtil.shutdown();
}
}

6. Persistence life style:

Given an instance of an object that is mapped to Hibernate, it can be in any one of


four different states: transient, persistent, detached, or removed.

Transient Object

Transient objects exist in heap memory. Hibernate does not manage transient objects or
persist changes to transient objects.

Transient objects are independent of Hibernate

To persist the changes to a transient object, you would have to ask the session to save
the transient object to the database, at which point Hibernate assigns the object an
identifier and marks the object as being in persistent state.
Persistent Object

Persistent objects exist in the database, and Hibernate manages the persistence for
persistent objects.

Persistent objects are


maintained by Hibernate

If fields or properties change on a persistent object, Hibernate will keep the database
representation up to date when the application marks the changes as to be committed.

Detached Object

Detached objects have a representation in the database, but changes to the object will
not be reflected in the database, and vice-versa. This temporary separation of the object
and the database is shown in image below.

Detached objects exist in the database


but are not maintained by Hibernate

A detached object can be created by closing the session that it was associated with, or
by evicting it from the session with a call to the session’s evict() method.

Removed Object

Removed objects are objects that are being managed by Hibernate (persistent objects,
in other words) that have been passed to the session’s remove() method. When the
application marks the changes held in the session as to be committed, the entries in the
database that correspond to removed objects are deleted.
7. Hibernate Entities Equality and Identity
➔ Object fetched from same session:

public static void main(String[] args)


{
Session sessionOne = HibernateUtil.getSessionFactory().openSession();
sessionOne.beginTransaction();

// Create new Employee object


EmployeeEntity emp = new EmployeeEntity();
emp.setFirstName("Rohit");
emp.setLastName("Patil");
//Save employee
sessionOne.save(emp);

sessionOne.getTransaction().commit();

//Get employee id
Integer genEmpId = emp.getEmployeeId();

//New session where we will fetch the employee two times and compare the
objects
Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
sessionTwo.beginTransaction();

EmployeeEntity employeeObj1 = (EmployeeEntity)


sessionTwo.get(EmployeeEntity.class, genEmpId);
EmployeeEntity employeeObj2 = (EmployeeEntity)
sessionTwo.get(EmployeeEntity.class, genEmpId);

//Checking equality
System.out.println(employeeObj1 == employeeObj2);

HibernateUtil.shutdown();
}

Output:

true

➔ Object fetched from d/f session:

System.out.println(emp == employeeObj1);

System.out.println(emp.equals(employeeObj1));

Output:

false
false

➔ With equals and hashcode()

@Entity

@Table(name = "Employee")
public class EmployeeEntity implements Serializable
{
private static final long serialVersionUID = -1798070786993154676L;
@Id
@Column(name = "ID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer employeeId;
@Column(name = "FIRST_NAME", unique = false, nullable = false, length
= 100)
private String firstName;
@Column(name = "LAST_NAME", unique = false, nullable = false, length
= 100)
private String lastName;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeeEntity)) return false;

EmployeeEntity otherEmployee = (EmployeeEntity) o;

if (getEmployeeId() != null ?
!getEmployeeId().equals(otherEmployee.getEmployeeId()) :
otherEmployee.getEmployeeId() != null)
return false;
if (getFirstName() != null ?
!getFirstName().equals(otherEmployee.getFirstName()) :
otherEmployee.getFirstName() != null)
return false;
if (getLastName() != null ?
!getLastName().equals(otherEmployee.getLastName()) :
otherEmployee.getLastName() != null)
return false;

return true;
}

@Override
public int hashCode() {
int result = getEmployeeId() != null ? getEmployeeId().hashCode() : 0;
result = 31 * result + (getFirstName() != null ?
getFirstName().hashCode() : 0);
result = 31 * result + (getLastName() != null?getLastName().hashCode()
: 0);
return result;
}
//Setters and Getters
}

Now lets again check the equality using equals() method. [‘==’ will return false, we
know that].
System.out.println(emp.equals(employeeObj1));

Output:

true

8. One To One Mapping:

In this example you will learn how to map one-to-one relationship using Hibernate
Annotations. Consider the following relationship between Student and Address entity.

According to the relationship each student should have a unique address.

To create this relationship you need to have a STUDENT and ADDRESS table. The relational
model is shown below.

@Entity
@Table(name = "STUDENT")
public class Student {
private long studentId;
private String studentName;
private Address studentAddress;

public Student() {
}

public Student(String studentName, Address studentAddress) {


this.studentName = studentName;
this.studentAddress = studentAddress;
}

@Id
@GeneratedValue
@Column(name = "STUDENT_ID")
public long getStudentId() {
return this.studentId;
}

public void setStudentId(long studentId) {


this.studentId = studentId;
}

@Column(name = "STUDENT_NAME", nullable = false, length = 100)


public String getStudentName() {
return this.studentName;
}

public void setStudentName(String studentName) {


this.studentName = studentName;
}

@OneToOne(cascade = CascadeType.ALL)
public Address getStudentAddress() {
return this.studentAddress;
}

public void setStudentAddress(Address studentAddress) {


this.studentAddress = studentAddress;
}

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

private long addressId;


private String street;
private String city;
private String state;
private String zipcode;

public Address() {
}

public Address(String street, String city, String state, String zipcod


e) {
this.street = street;
this.city = city;
this.state = state;
this.zipcode = zipcode;
}

@Id
@GeneratedValue
@Column(name = "ADDRESS_ID")
public long getAddressId() {
return this.addressId;
}

public void setAddressId(long addressId) {


this.addressId = addressId;
}

@Column(name = "ADDRESS_STREET", nullable = false, length=250)


public String getStreet() {
return this.street;
}

public void setStreet(String street) {


this.street = street;
}

@Column(name = "ADDRESS_CITY", nullable = false, length=50)


public String getCity() {
return this.city;
}

public void setCity(String city) {


this.city = city;
}

@Column(name = "ADDRESS_STATE", nullable = false, length=50)


public String getState() {
return this.state;
}

public void setState(String state) {


this.state = state;
}
@Column(name = "ADDRESS_ZIPCODE", nullable = false, length=10)
public String getZipcode() {
return this.zipcode;
}

public void setZipcode(String zipcode) {


this.zipcode = zipcode;
}

public class Main {

public static void main(String[] args) {


Session session = HibernateUtil.getSessionFactory().openSessio
n();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Address address1 = new Address("OMR Road", "Chennai", "
TN", "600097");
Address address2 = new Address("Ring Road", "Banglore",
"Karnataka", "560000");
Student student1 = new Student("Eswar", address1);
Student student2 = new Student("Joe", address2);
session.save(student1);
session.save(student2);
transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}

On executing the Main class you will see the following output.

The Student table has two records.

The Address table has two record.

Each student record points to a different address record, this illustrates the one-to-one
mapping.

9. One to Many:
In this example you will learn how to map one-to-many relationship using
Hibernate Annotations. Consider the following relationship
between Student and Phone entity.
According to the relationship a student can have any number of phone numbers.

To create this relationship you need to have


a STUDENT, PHONE and STUDENT_PHONE table. The relational model is shown
below.

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

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

@Entity
@Table(name = "STUDENT")
public class Student {

private long studentId;


private String studentName;
private Set<Phone> studentPhoneNumbers = new HashSet<Phone>();

public Student() {
}

public Student(String studentName, Set<Phone> studentPhoneNumbers) {


this.studentName = studentName;
this.studentPhoneNumbers = studentPhoneNumbers;
}

@Id
@GeneratedValue
@Column(name = "STUDENT_ID")
public long getStudentId() {
return this.studentId;
}

public void setStudentId(long studentId) {


this.studentId = studentId;
}

@Column(name = "STUDENT_NAME", nullable = false, length = 100)


public String getStudentName() {
return this.studentName;
}

public void setStudentName(String studentName) {


this.studentName = studentName;
}

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "STUDENT_PHONE", joinColumns = { @JoinColumn(name = "STUDENT
_ID") }, inverseJoinColumns = { @JoinColumn(name = "PHONE_ID") })
public Set<Phone> getStudentPhoneNumbers() {
return this.studentPhoneNumbers;
}
public void setStudentPhoneNumbers(Set<Phone> studentPhoneNumbers) {
this.studentPhoneNumbers = studentPhoneNumbers;
}

The @OneToMany annotation is used to create the one-to-many relationship between


the Student and Phone entities. The @JoinTable annotation is used to create
the STUDENT_PHONE link table and @JoinColumn annotation is used to refer the linking columns in
both the tables.

Phone class is used to create the PHONE table.

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

@Entity
@Table(name = "PHONE")
public class Phone {

private long phoneId;


private String phoneType;
private String phoneNumber;

public Phone() {
}

public Phone(String phoneType, String phoneNumber) {


this.phoneType = phoneType;
this.phoneNumber = phoneNumber;
}

@Id
@GeneratedValue
@Column(name = "PHONE_ID")
public long getPhoneId() {
return this.phoneId;
}

public void setPhoneId(long phoneId) {


this.phoneId = phoneId;
}

@Column(name = "PHONE_TYPE", nullable = false, length=10)


public String getPhoneType() {
return this.phoneType;
}

public void setPhoneType(String phoneType) {


this.phoneType = phoneType;
}

@Column(name = "PHONE_NUMBER", nullable = false, length=15)


public String getPhoneNumber() {
return this.phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {


this.phoneNumber = phoneNumber;
}

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

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.vaannila.util.HibernateUtil;

public class Main {

public static void main(String[] args) {


Session session = HibernateUtil.getSessionFactory().openSessio
n();
Transaction transaction = null;
try {
transaction = session.beginTransaction();

Set<Phone> phoneNumbers = new HashSet<Phone>();


phoneNumbers.add(new Phone("house","32354353"));
phoneNumbers.add(new Phone("mobile","9889343423"));

Student student = new Student("Eswar", phoneNumbers);


session.save(student);

transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}

On executing the Main class you will see the following output.

The STUDENT table has one record.


The PHONE table has two records.

The STUDENT_PHONE table has two records to link the student and phone numbers.

A single student record points to two phone numbers, this illustrates the one-to-many
mapping.

10. Many To One:


In this example, you will learn how to map many-to-one relationship using Hibernate
Annotations. Consider the following relationship between Student and Address entity.

According to the relationship many students can have the same address.

To create this relationship you need to have a STUDENT and ADDRESS table. The relational
model is shown below.
Student class
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "STUDENT")
public class Student {
private long studentId;
private String studentName;
private Address studentAddress;
public Student() {
}
public Student(String studentName, Address studentAddress) {
this.studentName = studentName;
this.studentAddress = studentAddress;
}
@Id
@GeneratedValue
@Column(name = "STUDENT_ID")
public long getStudentId() {
return this.studentId;
}
public void setStudentId(long studentId) {
this.studentId = studentId;
}
@Column(name = "STUDENT_NAME", nullable = false, length = 100)
public String getStudentName() {
return this.studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@ManyToOne(cascade = CascadeType.ALL)
public Address getStudentAddress() {
return this.studentAddress;
}
public void setStudentAddress(Address studentAddress) {
this.studentAddress = studentAddress;
}
}
Address class:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "ADDRESS")
public class Address {
private long addressId;
private String street;
private String city;
private String state;
private String zipcode;
public Address() {
}
public Address(String street, String city, String state, String zipcode) {
this.street = street;
this.city = city;
this.state = state;
this.zipcode = zipcode;
}
@Id
@GeneratedValue
@Column(name = "ADDRESS_ID")
public long getAddressId() {
return this.addressId;
}
public void setAddressId(long addressId) {
this.addressId = addressId;
}
@Column(name = "ADDRESS_STREET", nullable = false, length=250)
public String getStreet() {
return this.street;
}
public void setStreet(String street) {
this.street = street;
}
@Column(name = "ADDRESS_CITY", nullable = false, length=50)
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
@Column(name = "ADDRESS_STATE", nullable = false, length=50)
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
@Column(name = "ADDRESS_ZIPCODE", nullable = false, length=10)
public String getZipcode() {
return this.zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
}

Main class:
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.vaannila.util.HibernateUtil;
public class Main {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Address address = new Address("OMR Road", "Chennai", "TN", "600097");
//By using cascade=all option the address need not be saved explicitly when t
he student object is persisted the address will be automatically saved.
//session.save(address);
Student student1 = new Student("Eswar", address);
Student student2 = new Student("Joe", address);
session.save(student1);
session.save(student2);

transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}

On executing the Main class you will see the following output.

The Student table has two records.

The Address table has one record.


Both the student records points to the same address record, this illustrates the many-to-
one mapping.

11. Many To Many:


In this example you will learn how to map many-to-many relationship using
Hibernate Annotations. Consider the following relationship
between Student and Course entity.

According to the relationship a student can enroll in any number of courses and the
course can have any number of students.

To create this relationship you need to have


a STUDENT, COURSE and STUDENT_COURSE table. The relational model is shown
below.

Student class is used to create the STUDENT and STUDENT_COURSE table.

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

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

@Entity
@Table(name = "STUDENT")
public class Student {

private long studentId;


private String studentName;
private Set<Course> courses = new HashSet<Course>(0);

public Student() {
}

public Student(String studentName) {


this.studentName = studentName;
}

public Student(String studentName, Set<Course> courses) {


this.studentName = studentName;
this.courses = courses;
}

@Id
@GeneratedValue
@Column(name = "STUDENT_ID")
public long getStudentId() {
return this.studentId;
}

public void setStudentId(long studentId) {


this.studentId = studentId;
}

@Column(name = "STUDENT_NAME", nullable = false, length = 100)


public String getStudentName() {
return this.studentName;
}

public void setStudentName(String studentName) {


this.studentName = studentName;
}

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "STUDENT_COURSE", joinColumns = { @JoinColumn(name = "STUDEN
T_ID") }, inverseJoinColumns = { @JoinColumn(name = "COURSE_ID") })
public Set<Course> getCourses() {
return this.courses;
}

public void setCourses(Set<Course> courses) {


this.courses = courses;
}

Course class is used to create the COURSE table.

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

@Entity
@Table(name="COURSE")
public class Course {

private long courseId;


private String courseName;

public Course() {
}

public Course(String courseName) {


this.courseName = courseName;
}

@Id
@GeneratedValue
@Column(name="COURSE_ID")
public long getCourseId() {
return this.courseId;
}

public void setCourseId(long courseId) {


this.courseId = courseId;
}

@Column(name="COURSE_NAME", nullable=false)
public String getCourseName() {
return this.courseName;
}

public void setCourseName(String courseName) {


this.courseName = courseName;
}

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

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.vaannila.util.HibernateUtil;

public class Main {

public static void main(String[] args) {

Session session = HibernateUtil.getSessionFactory().openSession();


Transaction transaction = null;
try {
transaction = session.beginTransaction();

Set<Course> courses = new HashSet<Course>();


courses.add(new Course("Maths"));
courses.add(new Course("Computer Science"));
Student student1 = new Student("Eswar", courses);
Student student2 = new Student("Joe", courses);
session.save(student1);
session.save(student2);

transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}

}
}

On executing the Main class you will see the following output.

The STUDENT table has two records.

The COURSE table has two records.


The STUDENT_COURSE table has four records to link the student and courses.

Each student has enrolled in the same two courses, this illustrates the many-to-many
mapping.

12. @GeneratedValue:
The @GeneratedValue annotation is to configure the way of increment of the specified
column(field). For example when using Mysql, you may specify auto_increment in the
definition of table to make it self-incremental, and then use

@GeneratedValue(strategy = GenerationType.IDENTITY)

Or using Sequence:

@Id
@SequenceGenerator(name="seq",sequenceName="oracle_seq")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
private Integer pid;

13. Cascade types:


a. 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.
b. CascadeType.REMOVE: When we delete an entity all the entities held in this field
delete too.
c. CascadeType.REFRESH: When we refresh an entity all the entities held in this
field refresh too.
d. 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.
14. Lazy and Eager Loading:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "CHILD")
public class Child {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long childId;

@Column(name = "CHILD_NAME")
private String childName;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)


private Set<Toy> toyList = new HashSet<Toy>();

public Long getChildId() {


return childId;
}

public void setChildId(Long childId) {


this.childId = childId;
}

public String getChildName() {


return childName;
}

public void setChildName(String childName) {


this.childName = childName;
}

public Set<Toy> getToyList() {


return toyList;
}

public void addToy(Toy toy) {


toyList.add(toy);
}
}

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 = "TOYS")
public class Toy {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "TOY_ID")

private Long toyId;


@Column(name = "TOY_NAME")

private String toyName;

public Long getToyId() {


return toyId;
}

public void setToyId(Long toyId) {


this.toyId = toyId;
}

public String getToyName() {


return toyName;
}

public void setToyName(String toyName) {


this.toyName = toyName;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((toyName == null) ? 0 : toyName.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Toy other = (Toy) obj;
if (toyName == null) {
if (other.toyName != null)
return false;
} else if (!toyName.equals(other.toyName))
return false;
return true;
}

@Override
public String toString() {
return "Toy [toyId=" + toyId + ", toyName=" + toyName + "]";
}
}

If we still want to fetch data for toys (i.e. eager) then use Hibernate
template's initialize() method.

Normal (lazy):
public Child getChildByIdWithoutToys(Long childId) {
return getHibernateTemplate().get(Child.class, childId);
}

Eager:
public Child getChildByIdWithToys(Long childId) {
Child child = getChildByIdWithoutToys(childId);
getHibernateTemplate().initialize(child.getToyList());
return child;
}

15. HQL and Native Query:


HQL is an object-oriented query language, similar to SQL, but instead of operating on tables
and columns, HQL works with persistent objects and their properties.

HQL is a language with its own syntax and grammar. It is written as strings, like “from
Product p“. HQL queries are translated by Hibernate into conventional SQL
queries. Hibernate also provides an API that allows us to directly issue SQL queries as well.

➔ hql update statement example

Query query=session.createQuery("update Employee set age=:age123 where name=:name");


query.setInteger("age", 32);
query.setString("name", "Rohit Patil");
int modifications=query.executeUpdate();
➔ hql delete statement example
Query query=session.createQuery("delete from Account where accountstatus=:status");
query.setString("status", "purged");
int rowsDeleted=query.executeUpdate();

➔ hql insert statement example

An HQL INSERT cannot be used to directly insert arbitrary entities—it can only be used to insert entities constructed from
information obtained from SELECT queries (unlike ordinary SQL, in which an INSERT command can
be used to insert arbitrary data into a table, as well as insert values selected from other tables).

Query query=session.createQuery("insert into purged_accounts(id, code, status) "+


"select id, code, status from account where status=:status");
query.setString("status", "purged");
int rowsCopied=query.executeUpdate();

➔ hql select:
String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

String hql = "SELECT E.firstName FROM Employee E";


Query query = session.createQuery(hql);
List results = query.list();

String hql = "FROM Employee E WHERE E.id = 10";


Query query = session.createQuery(hql);
List results = query.list();

String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();

String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +


"GROUP BY E.firstName";
Query query = session.createQuery(hql);
List results = query.list();

String hql = "FROM Employee E WHERE E.id = :employee_id";


Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();

String hql = "SELECT count(distinct E.firstName) FROM Employee E";


Query query = session.createQuery(hql);
List results = query.list();

Pagination:
String hql = "FROM Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(10);
List results = query.list();

16. Criteria:

Following is the simplest example of a criteria query is one, which will simply return
every object that corresponds to the Employee class.
Criteria cr = session.createCriteria(Employee.class);
List results = cr.list();

Restriction:
Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.eq("salary", 2000));
List results = cr.list();

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000


cr.add(Restrictions.gt("salary", 2000));

// To get records having salary less than 2000


cr.add(Restrictions.lt("salary", 2000));

// To get records having fistName starting with zara


cr.add(Restrictions.like("firstName", "zara%"));

// Case sensitive form of the above restriction.


cr.add(Restrictions.ilike("firstName", "zara%"));

// To get records having salary in between 1000 and 2000


cr.add(Restrictions.between("salary", 1000, 2000));

// To check if the given property is null


cr.add(Restrictions.isNull("salary"));

// To check if the given property is not null


cr.add(Restrictions.isNotNull("salary"));

// To check if the given property is empty


cr.add(Restrictions.isEmpty("salary"));

// To check if the given property is not empty


cr.add(Restrictions.isNotEmpty("salary"));

And & Or:


Criteria cr = session.createCriteria(Employee.class);

Criterion salary = Restrictions.gt("salary", 2000);


Criterion name = Restrictions.ilike("firstNname","zara%");

// To get records matching with OR conditions


LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );

// To get records matching with AND conditions


LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );

List results = cr.list();


Sorting:

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000


cr.add(Restrictions.gt("salary", 2000));

// To sort records in descening order


cr.addOrder(Order.desc("salary"));

// To sort records in ascending order


cr.addOrder(Order.asc("salary"));

List results = cr.list();

Projection and Aggregation:


Criteria cr = session.createCriteria(Employee.class);

// To get total row count.


cr.setProjection(Projections.rowCount());

// To get average of a property.


cr.setProjection(Projections.avg("salary"));

// To get distinct count of a property.


cr.setProjection(Projections.countDistinct("firstName"));

// To get maximum of a property.


cr.setProjection(Projections.max("salary"));

// To get minimum of a property.


cr.setProjection(Projections.min("salary"));

// To get sum of a property.


cr.setProjection(Projections.sum("salary"));

17. Hibernate First Level Cache:


Fist level cache in hibernate is enabled by default and you do not need to do anything to get this
functionality working. In fact, you cannot disable it even forcefully.
It’s easy to understand the first level cache if we understand the fact that it is associated
with Session object. As we know session object is created on demand from session factory
and it is lost, once the session is closed. Similarly, first level cache associated with
session object is available only till session object is live. It is available to session object only
and is not accessible to any other session object in any other part of application.

➔ The loaded entity can be removed from session using evict() method. The next
loading of this entity will again make a database call if it has been removed using
evict() method.
➔ The whole session cache can be removed using clear() method. It will remove all
the entities stored in cache.

Example with same session:


//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

//fetch the department entity from database first time


DepartmentEntity department = (DepartmentEntity)
session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again


department = (DepartmentEntity)
session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

session.getTransaction().commit();
HibernateUtil.shutdown();

Output:
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_
from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource

Example: with new session

With new session, entity is fetched from database again irrespective


of it is already present in any other session in application.
//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Session sessionTemp = HibernateUtil.getSessionFactory().openSession();


sessionTemp.beginTransaction();
try
{
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again


department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

department = (DepartmentEntity) sessionTemp.load(DepartmentEntity.class, new Integer(1));


System.out.println(department.getName());
}
finally
{
session.getTransaction().commit();
HibernateUtil.shutdown();

sessionTemp.getTransaction().commit();
HibernateUtil.shutdown();
}

Output:

Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ wh


department0_.ID=?
Human Resource
Human Resource

Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ wh


department0_.ID=?
Human Resource

Clear and evict:


Here evict() is used to remove a particular object from cache associated with
session, and clear() method is used to remove all cached objects associated
with session. So they are essentially like remove one and remove all.

//Open the hibernate session


Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
try
{
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity)
session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

//fetch the department entity again


department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());

session.evict(department);
//session.clear();

department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));


System.out.println(department.getName());
}
finally
{
session.getTransaction().commit();
HibernateUtil.shutdown();
}

Output:

Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT


department0_ where department0_.ID=?
Human Resource
Human Resource

Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT


department0_ where department0_.ID=?
Human Resource
18. Second level cache:
Second level cache is created in session factory scope and is available to be used in all
sessions which are created using that particular session factory.
It also means that once session factory is closed, all cache associated with it die and cache
manager also closed down.

19.Mapped By: Used for bi directional mapping

@Entity

@Table(name = "STUDENT")
public class Student {

@Id
@GeneratedValue
@Column(name = "STUDENT_ID")
private long id;

@OneToOne(mappedBy="student", cascade = CascadeType.ALL)


private Address address;



}

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

@Id
@Column(name="ADDRESS_ID")
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign",parameters=@Parameter(name="property",
value="student"))
private long id;

@OneToOne
@PrimaryKeyJoinColumn
private Student student;



}
Note that now we have a student property in Address class and address property in
Student class, which means we can now navigate in either direction.In hibernate, for
bidirectional relationships like this, we have a concept of ownership, means who is the
owner of this relationship.Put simply, who is responsible for updating the column in DB
on which this relationship depends on. In our case it’s the student_id of Student table
which is driving the complete relationship truck. So we should tell hibernate that it’s the
Student class which will manage the relationship.

To do that, we can use mappedBy attribute. mappedBy attribute are always


put(annotated) on the inverse side of relation ship and specifies with it’s
attribute value, the owner of the relationship.

@OneToOne(mappedBy="student", cascade = CascadeType.ALL)


private Address address;
With this declaration, we ask hibernate to go and find the student property of
Address class to know how to manage the relationship/perform some operation.
Now in Address class , we have following declaration

@OneToOne
@PrimaryKeyJoinColumn
private Student student;
Which simply says that both the Address table and Student table share the same
primary key.

Unique constraint on class and field level

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

This code implies that both mask and group have to be unique, but separately. That means
that if, for example, you have a record with a mask.id = 1 and tries to insert another record
with mask.id = 1, you'll get an error, because that column should have unique values. The
same aplies for group.

On the other hand,


@Table(
name = "product_serial_group_mask",
uniqueConstraints = {@UniqueConstraint(columnNames = {"mask", "group"})}
)
Implies that the values of mask + group combined should be unique. That means you can
have, for example, a record with mask.id = 1 and group.id = 1, and if you try to insert another
record with mask.id = 1 and group.id = 2, it'll be inserted successfully, whereas in the first
case it wouldn't.

If you'd like to have both mask and group to be unique separately and to that at class level,
you'd have to write the code as following:

@Table(
name = "product_serial_group_mask",
uniqueConstraints = {
@UniqueConstraint(columnNames = "mask"),
@UniqueConstraint(columnNames = "group")
}
)

Why update not working on hbm2ddl.auto=update

id,fName, add(2500), year

hibernate.hbm2ddl.auto" value="update won't modify existing table column definitions. Doing


some testing I found that:

hibernate.hbm2ddl.auto" value="update will add a db column that doesn't already exist.

hibernate.hbm2ddl.auto" value="update will not delete a db column that is removed/no longer in


your entity.

hibernate.hbm2ddl.auto" value="update will not modify a db column that has already been
created.

You'll need to backup the table data, drop it and restart your application to get that table's
schema back in sync with your entity. Then reload your data.

You might also like