🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
Introduction
Caching in Hibernate can significantly improve the performance of your application by reducing the number of database queries. Hibernate supports two levels of caching:
- First-Level Cache: Also known as the session cache, it is associated with the
Sessionobject and is enabled by default. - Second-Level Cache: It is associated with the
SessionFactoryobject and must be explicitly configured.
In this tutorial, we will:
- Set up a Maven project with Hibernate and an H2 database dependency.
- Configure Hibernate and enable second-level caching.
- Create an entity class (
User). - Implement methods to demonstrate first-level and second-level caching.
- Demonstrate caching with a sample application.
Step 1: Set Up Your Project
1.1 Create a Maven Project
Open your IDE and create a new Maven project.
1.2 Add Dependencies
Update your pom.xml file to include the necessary dependencies for Hibernate, H2 (an in-memory database for simplicity), and EHCache (for second-level caching).
<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>hibernate-caching-example</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- Hibernate ORM --> <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>6.4.0.Final</version> </dependency> <!-- H2 Database --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.1.214</version> </dependency> <!-- EHCache --> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.9.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>21</source> <target>21</target> </configuration> </plugin> </plugins> </build> </project> 1.3 Configure Hibernate and Enable Second-Level Caching
Create a file named hibernate.cfg.xml in the src/main/resources directory to configure Hibernate and enable second-level caching.
<!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.dialect">org.hibernate.dialect.H2Dialect</property> <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.hbm2ddl.auto">update</property> <property name="hibernate.show_sql">true</property> <!-- Second-level cache configuration --> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.jcache.JCacheRegionFactory</property> <property name="hibernate.javax.cache.provider">org.ehcache.jsr107.EhcacheCachingProvider</property> <property name="hibernate.cache.use_query_cache">true</property> </session-factory> </hibernate-configuration> Create ehcache.xml Configuration File
Create a file named ehcache.xml in the src/main/resources directory to configure EHCache.
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ehcache.org/v3" xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd"> <cache alias="default"> <heap unit="entries">1000</heap> <expiry> <ttl unit="minutes">10</ttl> </expiry> </cache> <cache alias="com.example.entity.User"> <heap unit="entries">100</heap> <expiry> <ttl unit="minutes">10</ttl> </expiry> </cache> </config> Step 2: Create the Entity Class
Create an entity class User that will be mapped to a table in the database. This class uses annotations to define the entity and its fields, including cache configuration.
package com.example.entity; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // Getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } Explanation:
- The
@Entityannotation specifies that the class is an entity and is mapped to a database table. - The
@Idannotation specifies the primary key of the entity. - The
@GeneratedValue(strategy = GenerationType.IDENTITY)annotation specifies that the primary key is auto-incremented. - The
@Cacheannotation enables second-level caching for theUserentity.
Step 3: Create the Hibernate Utility Class
Create a utility class HibernateUtil to manage the Hibernate SessionFactory. This class ensures a single instance of SessionFactory is created and provides a method to close it.
package com.example.util; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml return new Configuration().configure().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(); } } Explanation:
- The
buildSessionFactorymethod creates theSessionFactoryfrom thehibernate.cfg.xmlconfiguration file. - The
getSessionFactorymethod returns the singleton instance ofSessionFactory. - The
shutdownmethod closes theSessionFactoryto release resources.
Step 4: Implement Caching
Create a class UserService to handle database operations with caching. This class includes methods to demonstrate first-level and second-level caching.
First-Level Cache Demonstration
package com.example.service; import com.example.entity.User; import com.example.util.HibernateUtil; import org.hibernate.Session; import org.hibernate.Transaction; public class UserService { public void demonstrateFirstLevelCache() { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); // Load user for the first time User user1 = session.get(User.class, 1L); System.out.println("First query: " + user1.getName()); // Load user again within the same session User user2 = session.get(User.class, 1L); System.out.println("Second query: " + user2.getName()); transaction.commit(); } catch (Exception e) { if (transaction != null) { transaction.rollback(); } e.printStackTrace(); } finally { session.close(); } } // Methods for second-level cache demonstration can be added here. } Second-Level Cache Demonstration
package com.example.service; import com.example.entity.User; import com.example.util.HibernateUtil; import org.hibernate.Session; import org.hibernate.Transaction; public class UserService { // First-level cache demonstration method public void demonstrateSecondLevelCache() { Session session1 = HibernateUtil.getSessionFactory().openSession(); Transaction transaction1 = null; try { transaction1 = session1.beginTransaction(); // Load user for the first time User user1 = session1.get(User.class, 1L); System.out.println("First session, first query: " + user1.getName()); transaction1.commit(); } catch (Exception e) { if (transaction1 != null) { transaction1.rollback(); } e.printStackTrace(); } finally { session1.close(); } // Open a new session and load the same user Session session2 = HibernateUtil.getSessionFactory().openSession(); Transaction transaction2 = null; try { transaction2 = session2.beginTransaction(); // Load user again in a new session User user2 = session2.get(User.class, 1L); System.out.println("Second session, first query: " + user2.getName()); transaction2.commit(); } catch (Exception e) { if (transaction2 != null) { transaction2.rollback(); } e.printStackTrace(); } finally { session2.close(); } } } Explanation:
- The
demonstrateFirstLevelCachemethod loads a user twice within the same session. The second query will not hit the database because the user is cached in the first-level cache. - The
demonstrateSecondLevelCachemethod loads a user in two different sessions. The second query will hit the second-level cache, avoiding a database hit.
Step 5: Demonstrate Caching
Create a MainApp class to demonstrate the caching functionality. This class calls the caching demonstration methods of UserService.
package com.example.main; import com.example.service.UserService; public class MainApp { public static void main(String[] args) { UserService userService = new UserService(); // Add a user to the database (for demonstration purposes) userService.createUser("Ramesh Fadatare", "ramesh.fadatare@example.com"); // Demonstrate first-level cache System.out.println("Demonstrating First-Level Cache:"); userService.demonstrateFirstLevelCache(); // Demonstrate second-level cache System.out.println("Demonstrating Second-Level Cache:"); userService.demonstrateSecondLevelCache(); } } Explanation:
-
Create a
UserServiceInstance:UserService userService = new UserService();An instance of
UserServiceis created to call its methods for performing database operations. -
Add a User to the Database:
userService.createUser("Ramesh Fadatare", "ramesh.fadatare@example.com");A user is added to the database for demonstration purposes.
-
Demonstrate First-Level Cache:
System.out.println("Demonstrating First-Level Cache:"); userService.demonstrateFirstLevelCache();The
demonstrateFirstLevelCachemethod is called to demonstrate the first-level cache functionality. -
Demonstrate Second-Level Cache:
System.out.println("Demonstrating Second-Level Cache:"); userService.demonstrateSecondLevelCache();The
demonstrateSecondLevelCachemethod is called to demonstrate the second-level cache functionality.
Sample Output
When you run the MainApp class, you should see the following output:
Demonstrating First-Level Cache: First query: Ramesh Fadatare Second query: Ramesh Fadatare Demonstrating Second-Level Cache: First session, first query: Ramesh Fadatare Second session, first query: Ramesh Fadatare This output indicates that the first-level cache was used to avoid a second database hit within the same session, and the second-level cache was used to avoid a second database hit across different sessions.
Conclusion
In this tutorial, we have successfully demonstrated how to implement caching in Hibernate. We set up a Hibernate project, created an entity class, and implemented caching functionality using first-level and second-level caches. This guide provides a solid foundation for improving the performance of your Hibernate-based applications through caching.
Comments
Post a Comment
Leave Comment