Unit IV
Unit IV
Hibernate is a powerful, open-source framework used for object-relational mapping (ORM) in Java. It
simplifies database interaction by mapping Java objects to database tables and vice versa.
Hibernate Framework
Hibernate is a Java framework that simplifies the development of Java application to interact with
the database. I
Hibernate implements the specifications of JPA (Java Persistence API) for data persistence.
What is JPA?
Java Persistence API (JPA) is a Java specification that provides certain functionality and standard to
ORM tools. The javax.persistence package contains the JPA classes and interfaces.
Hibernate framework is open source under the LGPL license and lightweight.
2) Fast Performance
The performance of hibernate framework is fast because cache is internally used in hibernate
framework. There are two types of cache in hibernate framework first level cache and second level
cache. First level cache is enabled by default.
HQL (Hibernate Query Language) is the object-oriented version of SQL. It generates the database
independent queries. So you don't need to write database specific queries. Before Hibernate, if
database is changed for the project, we need to change the SQL query as well that leads to the
maintenance problem.
Hibernate framework provides the facility to create the tables of the database automatically. So
there is no need to create tables in the database manually.
Hibernate supports Query cache and provide statistics about query and database status.
Hibernate Architecture
Below image shows the Hibernate architecture and how it works as an abstraction layer between
application classes and JDBC/JTA APIs for database operations. It’s clear that Hibernate is built on top
of JDBC and JTA APIs.
This is the high level architecture of Hibernate with mapping file and configuration file.
• Database layer
the core components of hibernate architecture:
• Persistent objects: Persistent objects are short-lived, single threaded objects that contains
persistent state and business function. These can be ordinary JavaBeans/POJOs. They are
associated with exactly one org.hibernate.Session.
• Transient objects: Transient objects are persistent classes instances that are not currently
associated with a org.hibernate.Session. They may have been instantiated by the application
and not yet persisted, or they may have been instantiated by a closed org.hibernate.Session.
To start using Hibernate we need to Install the necessary libraries and configure Hibernate to work
with your database. I'll walk you through each step clearly and concisely.
Hibernate Installation
There are two main ways to install Hibernate in your Java project:
2. Manually (Without Maven): You manually download and add JAR files to your project.
Maven is a build automation tool used primarily for managing Java projects and their dependencies.
If you’re using Maven, Hibernate dependencies are added to your `pom.xml` file.
Step 1: Ensure you have Maven installed. If not, download and install Maven from
(https://maven.apache.org/). Or create maven project in eclipse
Pom. xml
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.9.Final</version>
</dependency>
<!-- Database Driver (Example: MySQL) --> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
</dependencies>
```
Once you add these dependencies and save the `pom.xml` file, Maven will automatically download
the necessary libraries.
If you're not using Maven, you must manually download the required Hibernate JAR files and
configure them in your project.
-JDBC driver for the database you are using (e.g., MySQL, PostgreSQL, etc.).
For Eclipse:
- Right-click your project > Build Path> Add External Archives> Select all the downloaded JAR files.
2. Hibernate Configuration
Once Hibernate is installed, you need to configure it to connect to your database and to set up basic
properties. Hibernate can be configured via an XML file or using Java-based configuration
(annotation-based).
2.1 Hibernate Configuration Using XML (`hibernate.cfg.xml`)
Hibernate uses an XML configuration file called `hibernate.cfg.xml` where we define database
connection details and Hibernate-specific settings.
Step 1: Create a configuration file called `hibernate.cfg.xml` in the src/main/resources` directory (if
using Maven) or the `WEB-INF` directory (if in a web app).
```xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.show_sql">true</property>
<!-- Hibernate DDL Auto (optional: options are create, update, validate, none) -->
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.current_session_context_class">thread</property>
<property
name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
</session-factory>
</hibernate-configuration>
```
- `hibernate.dialect`: Specifies the database dialect. In this case, `MySQLDialect` is used for MySQL.
- `hibernate.hbm2ddl.auto`: Specifies how Hibernate will handle the schema (e.g., `create`, `update`,
`validate`).
Alternatively, you can configure Hibernate using Java-based configuration if you're using frameworks
like Spring. Here’s an example of how to configure Hibernate with Spring:
```java
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.example")
@Bean
sessionFactory.setDataSource(dataSource());
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
@Bean
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
@Bean
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private Properties hibernateProperties() {
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.hbm2ddl.auto", "update");
return properties;
```
- `hibernateProperties()`: Specifies Hibernate's settings (such as dialect, SQL logging, and DDL auto-
generation).
---
Once you’ve installed and configured Hibernate, it’s time to test it by creating an entity and
performing a basic operation.
```java
@Entity
@Table(name = "Employee")
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "name")
@Column(name = "salary")
```
```java
// Setup Hibernate
// Open session
try {
// Start a transaction
session.beginTransaction();
session.save(tempEmployee);
session.getTransaction().commit();
} finally {
factory.close();
```
Conclusion
In summary:
1. Install Hibernate using Maven or manually by adding the required JAR files.
3. Test the setup by creating an entity class, saving an object, and ensuring Hibernate performs
database operations as expected.
In Hibernate, mapping Java objects to database tables is crucial for performing CRUD operations.
While Hibernate offers annotation-based mapping, XML-based mapping was the original way of
configuring the mappings. This is still widely used in legacy systems or when annotations are not
suitable for your needs.
5. Inheritance Mapping
Employee.hbm.xml
<hibernate-mapping>
<generator class="identity"/>
</id>
</class>
</hibernate-mapping>
Example
id INT AUTO_INCREMENT PRIMARY KEY, -- The ID field (primary key) with auto-increment for
automatic generation.
name VARCHAR(100), -- The name field, which will store the employee's name.
salary DOUBLE -- The salary field, which will store the employee's salary.
);
package com.example.model;
public Employee() {}
this.salary = salary;
return id;
this.id = id;
return name;
this.name = name;
return salary;
this.salary = salary;
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property
name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property
name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<mapping resource="Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
<hibernate-mapping>
<generator class="increment"/>
</id>
</class>
</hibernate-mapping>
package com.example;
import com.example.model.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
try {
// Start a transaction
session.beginTransaction();
session.save(employee);
session.getTransaction().commit();
System.out.println("Employee saved: " + employee.getName());
} finally {
session.close();
sessionFactory.close();
If you're using Maven, you'll have a pom.xml file that includes the dependencies for Hibernate and
MySQL JDBC. Here's an example:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>HibernateExample</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.9.Final</version>
</dependency>
<!-- MySQL JDBC Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
</dependencies>
</project>
Hibernate is a full object/relational mapping solution that not only shields the developer from the
details of the underlying database management system, but also offers state management of
objects. This is, contrary to the management of SQL statements in common JDBC/SQL persistence
layers, a natural object-oriented view of persistence in Java applications.
In other words, Hibernate application developers should always think about the state of their
objects, and not necessarily about the execution of SQL statements. This part is taken care of by
Hibernate and is only relevant for the application developer when tuning the performance of the
system.
Hibernate Lifecycle
In Hibernate, either we create an object of an entity and save it into the database, or we fetch the
data of an entity from the database. Here, each entity is associated with the lifecycle. The entity
object passes through the different stages of the lifecycle.
o Transient state
o Persistent state
o Detached state
Transient state
o Once we create an instance of POJO class, then the object entered in the transient state.
o Here, an object is not associated with the Session. So, the transient state is not related to any
database.
o Hence, modifications in the data don't affect any changes in the database.
o The transient objects exist in the heap memory. They are independent of Hibernate.
e.setId(101);
e.setFirstName("Gaurav");
e.setLastName("Chawla");
Persistent state
o As soon as the object associated with the Session, it entered in the persistent state.
o Hence, we can say that an object is in the persistence state when we save or persist it.
session.save(e);
session.persist(e);
session.update(e);
session.saveOrUpdate(e);
session.lock(e);
session.merge(e);
Detached State
Once we either close the session or clear its cache, then the object entered into the
detached state.
As an object is no more associated with the Session, modifications in the data don't
affect any changes in the database.
However, the detached object still has a representation in the database.
If we want to persist the changes made to a detached object, it is required to reattach
the application to a valid Hibernate session.
To associate the detached object with the new hibernate session, use any of these
methods - load(), merge(), refresh(), update() or save() on a new session with the
reference of the detached object.
session.close();
session.clear();
session.detach(e);
session.evict(e);
Inheritance Mapping
Inheritance is a core concept in object-oriented programming (OOP) where a class (subclass) can
inherit fields and methods from another class (superclass). Hibernate supports inheritance mapping
to allow developers to map such inheritance relationships to relational database tables.
Hibernate supports three types of inheritance mapping strategies for mapping object-oriented
inheritance to relational database tables:
• In this strategy, a single table is used for all classes in the inheritance hierarchy. A
discriminator column is added to the table to differentiate between different types
of entities (subclasses).
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "animal_type", discriminatorType =
DiscriminatorType.STRING)
public class Animal {
@Id
private Long id;
@Entity
@DiscriminatorValue("Dog")
public class Dog extends Animal {
private String breed;
@DiscriminatorColumn adds a column (animal_type) that differentiates between Dog and Cat.
@DiscriminatorValue assigns a specific value for each subclass ("Dog" and "Cat").
In this strategy, each class in the inheritance hierarchy is mapped to its own table, and there is a join
between the tables for querying the full entity.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Id
@Entity
@Entity
1. Animal table:
id name
1 Fido
2 Whiskers
2. Dog table:
id breed
1 Labrador
3. Cat table:
id color
2 Gray
In this strategy, each class in the inheritance hierarchy is mapped to its own table, and there are no
joins. Each table contains all the fields from the parent class as well as its own.
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Id
@Entity
@Entity
1. Animal table:
id name
1 Fido
2 Whiskers
2. Dog table:
id name breed
1 Fido Labrador
3. Cat table:
id name color
2 Whiskers Gray
In Hibernate, collection mapping is used to represent relationships between entities that are "one-
to-many" or "many-to-many". Collections in Hibernate are typically represented using List, Set, or
Map in Java.
a) One-to-Many Collection Mapping
In a one-to-many relationship, a parent entity has a collection of child entities. For example, one
Customer can have many Orders.
@Entity
@Id
@OneToMany(mappedBy = "customer")
@Entity
@Id
@ManyToOne
@JoinColumn(name = "customer_id")
@ManyToOne in the Order entity indicates that many orders can belong to one customer.
@JoinColumn(name = "customer_id") specifies the foreign key column in the Order table.
In a many-to-many relationship, both entities have a collection of the other. For example, a Student
can enroll in many Course instances, and each Course can have many Students.
@Entity
@Id
@ManyToMany
@JoinTable(
name = "student_course",
@Entity
@Id
@ManyToMany(mappedBy = "courses")
@ManyToMany is used on both Student and Course to indicate the many-to-many relationship.
@JoinTable specifies the join table that maps the relationship (student_course).
@JoinColumn and inverseJoinColumns define the foreign key columns in the join table.
You can use a Set instead of a List for collections to avoid duplicates, as Set does not allow repeated
elements.
@Entity
@Id
@OneToMany(mappedBy = "customer")
In Hibernate, `Map` is a type of collection that can be used to represent relationships where each
element in the collection is a key-value pair. The key is typically an identifier, and the value is an
associated entity or value object. Hibernate provides support for mapping collections of type `Map`
using annotations like `@ElementCollection`, `@OneToMany`, or `@ManyToMany` along with
`@MapKey` and `@MapKeyColumn` to specify how the mapping should occur.
You can map a `Map` collection in Hibernate using two primary use cases:
1. Map of simple types (using `@ElementCollection`)
If you want to map a `Map` where the values are simple types (e.g., `String`, `Integer`, etc.), you can
use the `@ElementCollection` annotation to map the collection, and `@MapKey` to specify the map's
key.
Here’s an example where a `Person` entity has a `Map<Integer, String>` representing a collection of
phone numbers with area codes as keys:
```java
@Entity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
// Map of phone numbers where the key is the area code (Integer) and the value is the phone
number (String)
@ElementCollection
@MapKeyColumn(name = "area_code")
@Column(name = "phone_number")
return id;
this.id = id;
return name;
this.name = name;
return phoneNumbers;
this.phoneNumbers = phoneNumbers;
```
Key points:
- `@Column`: Specifies the column that will hold the value of the map. Here, it will store the phone
number.
Database Schema:
Hibernate will automatically create a table to store the map. The table might look like this:
|-----------|-----------|--------------|
|1 | 123 | 555-1234 |
|1 | 456 | 555-5678 |
---
In some cases, you might want to map a `Map` where the values are entities rather than simple
types. For example, a `Customer` entity might have a `Map<String, Order>`, where the key is an order
number (or another unique identifier), and the value is an `Order` entity.
Let’s say a `Customer` has a `Map<String, Order>` where the key is the order number (String) and the
value is an `Order` entity.
```java
@Entity
@GeneratedValue(strategy = GenerationType.IDENTITY)
// Map of orders where the key is the order number (String) and the value is an Order entity
@OneToMany(mappedBy = "customer")
return id;
this.id = id;
return name;
this.name = name;
return orders;
}
public void setOrders(Map<String, Order> orders) {
this.orders = orders;
@Entity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ManyToOne
@JoinColumn(name = "customer_id")
return id;
this.id = id;
return orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
return customer;
this.customer = customer;
```
Key points:
- `@MapKey(name = "orderNumber")`: Specifies that the key for the `Map` will be the
`orderNumber` of the `Order` entity. Hibernate will use this field as the map key.
- `mappedBy`: Specifies that the `Order` entity owns the relationship and `customer` is the owning
side.
Database Schema:
For the `Customer`-`Order` relationship, you might see the following tables:
1. Customer Table:
| id | name |
|----|-------|
| 1 | John |
2. Order Table:
| id | order_number | customer_id |
|----|--------------|-------------|
| 1 | A123 |1 |
| 2 | B456 |1 |
The `Order` table will have a foreign key (`customer_id`) referencing the `Customer` table.
---
If the relationship is many-to-many, you can map a `Map` collection using `@ManyToMany` with a
`Map` key-value pair.
Let's say you want to store a `Map<Course, Integer>`, where each `Course` entity is mapped to a
grade for a `Student`.
```java
@Entity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
// Map of courses where the key is the course and the value is the grade
@ManyToMany
@JoinTable(
name = "student_course_grades",
joinColumns = @JoinColumn(name = "student_id"),
return id;
this.id = id;
return name;
this.name = name;
return coursesAndGrades;
this.coursesAndGrades = coursesAndGrades;
}
@Entity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
return id;
this.id = id;
return courseName;
this.courseName = courseName;
- `@ElementCollection`: Maps simple values (like `Integer`, `String`) in a collection (like `Map`).
- `@MapKeyColumn`: Specifies the column that stores the key in a map (for simple types).
- `@MapKey`: Specifies the field of the entity to be used as the key in the map.
Hibernate Query Language (HQL) is a powerful and flexible query language designed for querying
data from a database in Hibernate-based applications. It is an object-oriented query language similar
to SQL but operates on Hibernate entities (Java objects) rather than directly on database tables.
HQL allows developers to query, update, and delete persistent entities, and it provides several
advantages, such as abstracting away the underlying database's SQL syntax, allowing you to work
with your Java domain model directly.
1. Object-Oriented: HQL queries operate on persistent objects rather than database tables. You
query classes, properties, and relationships as Java objects.
2. Cross-Database Compatibility: Since HQL abstracts away the database's SQL syntax, it helps
create database-independent queries.
3. Supports Joins: HQL supports joining multiple entities, both one-to-many and many-to-many
relationships, which is important when querying complex domain models.
4. Supports Aggregates: HQL supports aggregate functions like COUNT, SUM, AVG, MIN, MAX,
etc., for calculations.
5. Supports Pagination: You can limit the number of results returned using setFirstResult() and
setMaxResults() for pagination.
6. Uses Entity Names: Unlike SQL, HQL uses the entity class names (not table names) and the
property names (not column names) for queries.
1. Selecting Data: You can use HQL to select entities and their properties (fields) from the
database.
java
String hql = "FROM Employee"; // This will select all employees (where Employee is a mapped
entity).
2. Selecting Specific Fields: You can also select specific fields from entities rather than returning
full entity objects.
java
String hql = "SELECT e.name, e.salary FROM Employee e"; // Selects name and salary fields from
Employee.
List<Object[]> result = query.list(); // Returns a list of Object arrays containing name and salary.
3. Where Clause: You can filter results using the WHERE clause to specify conditions.
java
String hql = "FROM Employee e WHERE e.salary > :salary"; // Select employees with salary greater
than a specific value.
4. Order By Clause: To sort results, you can use the ORDER BY clause.
String hql = "FROM Employee e ORDER BY e.salary DESC"; // Sort employees by salary in descending
order.
5. Aggregates: HQL supports aggregate functions such as COUNT(), SUM(), MAX(), MIN(), and
AVG().
String hql = "SELECT COUNT(e) FROM Employee e"; // Get the count of employees.
Below is a simple and basic example of using Hibernate with HQL. This example will focus on the
following:
1. Create a simple entity (`Employee`).
---
This file configures Hibernate to connect to a database. We'll use an H2 in-memory database for
simplicity.
```xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.url">jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-
1</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<!-- Specify dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property
name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
</session-factory>
</hibernate-configuration>
```
---
```java
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
@Id
private int id;
// Constructors
public Employee() {}
this.id = id;
this.name = name;
return id;
this.id = id;
return name;
this.name = name;
```
---
Step 3: Hibernate Utility Class (`HibernateUtil.java`)
```java
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
static {
try {
sessionFactory = new
Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(Employee.class).buildSessionFact
ory();
return sessionFactory;
getSessionFactory().close();
```
---
2. Query the database using HQL to fetch and display the employee.
```java
import org.hibernate.Session;
import org.hibernate.query.Query;
import java.util.List;
try {
// Start a transaction
session.beginTransaction();
session.save(emp);
// Commit the transaction
session.getTransaction().commit();
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.getTransaction().commit();
} finally {
HibernateUtil.shutdown();
```
---
Step 5: Dependencies (for Maven)
```xml
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
```
---
How It Works:
1. Hibernate Configuration: The `hibernate.cfg.xml` file contains all Hibernate settings, including the
database connection details, dialect, and the configuration for automatic schema generation.
2. Employee Entity: This entity class is annotated with `@Entity` and `@Id`, representing the
employee data.
3. HibernateUtil: This utility class manages the Hibernate session factory. It initializes the session
factory and provides access to the session factory in the application.
4. Main Program: In the `Main.java` class:
- We then use an HQL query (`FROM Employee`) to retrieve all employee records from the
database.
Hibernate Caching
This is where caching comes in. Caching is a technique that allows frequently accessed data to be
stored in memory so that it can be quickly retrieved without having to go back to the database
every time. By caching data, Hibernate can reduce the number of database queries it needs to
execute, improving performance and reducing the load on the database server.
First-level caching is an in-built caching mechanism provided by Hibernate that stores the data in the
memory of the Session object. Whenever an entity is fetched from the database, it is stored in the
cache. If the same entity is requested again within the same session, Hibernate retrieves it from the
cache instead of hitting the database. This can significantly improve the performance of the
application by reducing the number of database queries.
The first-level cache has session-level scope, which means that the data stored in the cache is
available only within the session. When the session is closed, the cache is cleared automatically. The
cache is also not shared between different sessions, which means that each session has its own
separate cache.
Hibernate manages the first-level cache automatically, and there is no need to configure it manually.
The cache is enabled by default and can’t be turned off. When an entity is fetched from the database,
Hibernate checks if it is already present in the cache. If it is, the cached entity is returned, otherwise,
Hibernate fetches the entity from the database and stores it in the cache.
2. Second-Level Cache
Second-level caching is an optional caching mechanism provided by Hibernate that stores data across
sessions. It is more powerful than first-level caching, which is limited to a single session.
To enable Second-level Caching in Hibernate, you need to configure a cache provider in your
Hibernate configuration file. Hibernate supports multiple cache providers such as Ehcache,
Infinispan, and Hazelcast. You also need to annotate the entities that you want to cache with the
@Cacheable annotation.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernate.version}</version>
</dependency>
3. Annotate Entities:
To enable caching for an entity, annotate it with the @Cacheable annotation. You can also
specify the cache concurrency strategy using the @Cache annotation.
@Data
@Entity
@Table(name = "users")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
The scope of Second-level Caching in Hibernate is application-level, which means that the cached
data is available across multiple sessions.
Hibernate supports three cache modes for Second-level Caching: read-only, read-write, and
transactional. The read-only cache mode is used for data that is not expected to change frequently.
The read-write cache mode is used for data that is frequently updated. The transactional cache
mode is used for data that is updated within a transaction.
The cache concurrency strategy determines how multiple threads access the cache. Hibernate
supports multiple cache concurrency strategies such
as READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, and TRANSACTIONAL.
To ensure data consistency, Hibernate provides a cache synchronization mechanism that
automatically updates the cache when the database is updated. This mechanism is called cache
invalidation. When an entity is updated, Hibernate invalidates the corresponding cache entry, and
the next time the entity is accessed, it is fetched from the database and stored in the cache.
. Query Cache
Query caching is a caching mechanism provided by Hibernate to cache the results of queries. When a
query is executed, Hibernate checks if the query results are already cached. If the results are found in
the cache, they are returned without hitting the database, otherwise, the query is executed and the
results are cached for future use.
To enable query caching in Hibernate, you need to set
the hibernate.cache.use_query_cache property to true.
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheReg
ionFactory
@Repository
public interface AuthorRepository extends CrudRepository<Author, Integer> {
@QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") })
Author findByName(String name);
}
Configuring Caching in Hibernate
Hibernate provides various configuration properties to enable and configure caching. Here are some
of the commonly used properties:
1. hibernate.cache.use_second_level_cache - Set this to true to enable the second-level cache.
2. hibernate.cache.region.factory_class - This property specifies the caching provider to be used for the
second-level and query cache. For example, to use EHCache, set it
to org.hibernate.cache.ehcache.EhCacheRegionFactory.
3. hibernate.cache.use_query_cache - Set this to true to enable the query cache.
4. hibernate.cache.provider_configuration_file_resource_path - This property specifies the path to the
configuration file for the caching provider. For example, for EHCache, it can be set to ehcache.xml.
But if we are going to integrate the hibernate application with spring, we don't need to create the
hibernate.cfg.xml file. We can provide all the information in the applicationContext.xml file.
The Spring framework provides HibernateTemplate class, so you don't need to follow so many steps
like create Configuration, BuildSessionFactory, Session, beginning and committing transaction etc.
cfg.configure("hibernate.cfg.xml");
SessionFactory factory=cfg.buildSessionFactory();
Session session=factory.openSession();
Transaction t=session.beginTransaction();
t.commit();//transaction is commited
session.close();
As you can see in the code of sole hibernate, you have to follow so many steps.
Now, you don't need to follow so many steps. You can simply write this:
hibernateTemplate.save(e1);
Steps
Let's see what are the simple steps for hibernate and spring integration:
In this example, we are using the Oracle as the database, but you may use any database. Let's create
the table in the oracle database
"SALARY" FLOAT(126),
2) Employee.java
It is a simple POJO class. Here it works as the persistent class for hibernate.
package com.example;
3) employee.hbm.xml
This mapping file contains all the information of the persistent class.
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<id name="id">
<generator class="assigned"></generator>
</id>
<property name="name"></property>
<property name="salary"></property>
</class>
</hibernate-mapping>
4) EmployeeDao.java
It is a java class that uses the HibernateTemplate class method to persist the object of Employee
class.
package com.example;
import org.springframework.orm.hibernate3.HibernateTemplate;
import java.util.*;
HibernateTemplate template;
this.template = template;
template.update(e);
template.delete(e);
Employee e=(Employee)template.get(Employee.class,id);
return e;
list=template.loadAll(Employee.class);
return list;
}
applicationContext.xml
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</bean>
<property name="mappingResources">
<list>
<value>employee.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
</bean>
</bean>
</beans>
InsertTest.java
This class uses the EmployeeDao class object and calls its saveEmployee method by passing the
object of Employee class.
package com.example;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
EmployeeDao dao=(EmployeeDao)factory.getBean("d");
e.setId(114);
e.setName("varun");
e.setSalary(50000);
dao.saveEmployee(e);