DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Querydsl vs. JPA Criteria, Part 6: Upgrade Guide To Spring Boot 3.2 for Spring Data JPA and Querydsl Project
  • Enhanced Query Caching Mechanism in Hibernate 6.3.0
  • Implement Hibernate Second-Level Cache With NCache
  • Auditing Spring Boot Using JPA, Hibernate, and Spring Data JPA

Trending

  • Analyzing Techniques to Provision Access via IDAM Models During Emergency and Disaster Response
  • Can You Run a MariaDB Cluster on a $150 Kubernetes Lab? I Gave It a Shot
  • Scaling Microservices With Docker and Kubernetes on Production
  • Integrating Model Context Protocol (MCP) With Microsoft Copilot Studio AI Agents
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. How To Integrate NCache With JPA Hibernate for Caching in Spring Boot Applications

How To Integrate NCache With JPA Hibernate for Caching in Spring Boot Applications

In this article, let’s discuss the caching feature of Hibernate with NCache for caching in a Spring Boot application with an illustrating example.

By 
Sriram Kumar Mannava user avatar
Sriram Kumar Mannava
·
Feb. 20, 24 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
5.3K Views

Join the DZone community and get the full member experience.

Join For Free

What Is JPA Hibernate?

Hibernate is one of the most popular Object Relational Mapper (ORM) libraries for Java and Spring applications. It helps developers connect to and work with relational databases from Java applications without having to write SQL queries. The library implements the JPA (Java Persistence API) specification and provides several additional features that help develop persistence in applications faster and easier.

Caching in JPA Hibernate

One of the cool features supported by Hibernate is caching. Hibernate supports two levels of caching — L1 and L2. L1 cache is enabled by default and works within an application scope, so it cannot be shared across multiple threads. For example, if you have a scaled microservice application that reads and writes to a table in a relational database setup, this L1 cache is maintained individually within each of these containers where the microservice is running.

L2 cache is an external pluggable interface, using which we can cache frequently accessed data in an external caching provider via Hibernate. In this case, the cache is maintained out of session and can be shared across the microservice stack (in the above example).

Hibernate supports L2 cache with most of the popular caching providers like Redis, Ignite, NCache, etc.

What Is NCache?

NCache is one of the most popular distributed caching providers available in the market. It offers several features and supports integration with popular programming stacks like .NET, Java, etc.

NCache comes in several flavors — open source, professional, and enterprise and you can choose from these based on the features they offer.

Integrating NCache With Hibernate

NCache supports integration with Hibernate as L2 Cache and also for query caching. By using an external distributed cache cluster, we can ensure that frequently accessed entities are cached and used across the microservices in a scaled environment without putting unwanted load on the database layer. This way, the database calls are kept as minimal as possible, and the application performance is optimized as well.

To get started, let’s add the necessary packages to our spring boot project. To demonstrate, I’m going with a JPA Repository that uses Hibernate ORM to work with the relational database — MySQL setup.

Dependencies in my pom.xml file looks like this:

XML
 
<dependencies>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-actuator</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-data-jpa</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>


        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-devtools</artifactId>

            <scope>runtime</scope>

            <optional>true</optional>

        </dependency>

        <dependency>

            <groupId>com.mysql</groupId>

            <artifactId>mysql-connector-j</artifactId>

            <scope>runtime</scope>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.springframework.security</groupId>

            <artifactId>spring-security-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>


My JPARepository reads and writes to a table called books in my MySQL database. The repository and the entity looks like the following:

Java
 
package com.myjpa.helloapp.repositories;
import com.myjpa.helloapp.models.entities.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BookRepository extends JpaRepository<Book, Integer> {}
Java
 
package com.myjpa.helloapp.models.entities;

import jakarta.persistence.*;
import java.util.Date;
import org.hibernate.annotations.CreationTimestamp;

@Entity(name = "Book")
@Table(name = "Book")
public class Book {
  @Id @GeneratedValue(strategy = GenerationType.AUTO) private int bookId;
  @Column(name = "book_name") private String bookName;
  @Column(name = "isbn") private String isbn;
  @CreationTimestamp @Column(name = "created_date") private Date createdDate;

  public Book() {}

  public Book(String bookName, String isbn) {
    this.bookName = bookName;
    this.isbn = isbn;
  }
  public int getBookId() {
    return bookId;
  }
  public String getBookName() {
    return bookName;
  }
  public String getIsbn() {
    return isbn;
  }
  public Date getCreatedDate() {
    return createdDate;
  }
}


A BookService interacts with this repository and exposes GET and INSERT functionalities.

Java
 
package com.myjpa.helloapp.services;

import com.myjpa.helloapp.models.entities.Book;
import com.myjpa.helloapp.repositories.BookRepository;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service

public class BookService {
  @Autowired

  private BookRepository repository;

  public int createNew(String bookName, String isbn) {
    var book = new Book(bookName, isbn);

    // save the entity

    repository.save(book);

    // commit the changes

    repository.flush();

    // return the generated id

    var bookId = book.getBookId();

    return bookId;
  }

  public Book findBook(int id) {
    var entity = repository.findById(id);

    if (entity.isPresent()) {
      return entity.get();
    }

    return null;
  }
}


While this setup works perfectly fine, we haven’t added any caching to this. Let’s see how we can integrate caching to Hibernate with NCache as the provider.

L2 Caching With NCache

To Integrate NCache with Hibernate, we will add two more dependencies to our project. These are shown below:

XML
 
<dependency>

            <groupId>com.alachisoft.ncache</groupId>

            <artifactId>ncache-hibernate</artifactId>

            <version>5.3.2</version>

        </dependency>

        <dependency>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-jcache</artifactId>

            <version>6.4.2.Final</version>

        </dependency>


We will also add a Hibernate.cfg.xml file where we will configure the second-level cache and details  below:

XML
 
<hibernate-configuration>

  <session-factory>

    <property name="hibernate.cache.use_second_level_cache">true</property>

    <property name="hibernate.cache.region.factory_class">JCacheRegionFactory</property>

    <property name="hibernate.javax.cache.provider" >com.alachisoft.ncache.hibernate.jcache.HibernateNCacheCachingProvider</property>

    <property name="ncache.application_id">booksapi</property>

</session-factory>

</hibernate-configuration>


On top of the Entity Book, we will add an annotation that will set the cache status for the entity:

Java
 
@Entity(name = "Book")
@Table(name = "Book")
@Cache(region = "demoCache", usage = CacheConcurrencyStrategy.READ_WRITE)
public class Book {}


I’m indicating that my entities will be cached under the region demoCache, which is basically my cache cluster name.

I’d also place my client.nconf and config.nconf files, which contain information about the cache cluster and its network details in the root directory of my project.

The client.nconf looks like below:

XML
 
<?xml version="1.0" encoding="UTF-8"?>

<!-- Client configuration file is used by client to connect to out-proc caches.

Light weight client also uses this configuration file to connect to the remote caches.

This file is automatically generated each time a new cache/cluster is created or

cache/cluster configuration settings are applied.

-->

<configuration>

    <ncache-server connection-retries="5" retry-connection-delay="0" retry-interval="1"

        command-retries="3" command-retry-interval="0.1" client-request-timeout="90"

        connection-timeout="5" port="9800" local-server-ip="192.168.0.108" enable-keep-alive="False"

        keep-alive-interval="0" />

    <cache id="demoCache" client-cache-id="" client-cache-syncmode="optimistic"

        skip-client-cache-if-unavailable="False" reconnect-client-cache-interval="10"

        default-readthru-provider="" default-writethru-provider="" load-balance="True"

        enable-client-logs="True" log-level="info">

        <server name="192.168.0.108" />

    </cache>

</configuration>


When I run my application with this setup and do a GET operation for a single book, Hibernate looks up the entity in the NCache cluster and returns the cache entity; if it is not present, it shows a cache miss.

a GET operation

the NCache cluster

cache entity

Query Caching With NCache

Another feature of Hibernate that NCache fully supports is query caching. In this approach, the result set of a query can be cached for frequently accessed data. This ensures that the database is not frequently queried for frequently accessed data. This is specific for HQL (Hibernate Query Language) queries.

To enable Query Caching, I’ll simply add another line to the Hibernate.cfg.xml below:

XML
 
<property name="hibernate.cache.use_query_cache">true</property>


In the repository, I’d create another method that will run a specific query, and the result is cached.

Java
 
@Repository

public interface BookRepository extends JpaRepository<Book, Integer> {


    @Query(value = "SELECT p FROM Book p WHERE bookName like 'T%'")

    @Cacheable(value = "demoCache")

    @Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "demoCache")

    @QueryHints(value = { @QueryHint(name = "org.hibernate.cacheable", value = "true") })

    public List<Book> findAllBooks();

}


In this method, I’m querying for all Books that start with the letter T, and the result set is to be cached. For this, I’ll add a query hint that will set the caching to true.

When we hit the API that calls this method, we can see that the entire dataset is now cached.

the entire dataset is now cached

Conclusion

Caching is one of the most used strategies in building distributed applications. In a microservice architecture, where one application is scaled to X times based on the load, frequently hitting a database for data can be costly. 

Caching providers like NCache provide an easy and pluggable solution to Java microservices that use Hibernate for querying databases. In this article, we have seen how to use NCache as an L2 Cache for Hibernate and use it to cache individual entities and query caching.

Cache (computing) Hibernate Spring Boot Java Persistence API

Opinions expressed by DZone contributors are their own.

Related

  • Querydsl vs. JPA Criteria, Part 6: Upgrade Guide To Spring Boot 3.2 for Spring Data JPA and Querydsl Project
  • Enhanced Query Caching Mechanism in Hibernate 6.3.0
  • Implement Hibernate Second-Level Cache With NCache
  • Auditing Spring Boot Using JPA, Hibernate, and Spring Data JPA

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!