Skip to content

Add caching example with Spring Data Redis #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 20, 2025
Merged

Conversation

rashidi
Copy link
Owner

@rashidi rashidi commented Jul 20, 2025

No description provided.

@rashidi rashidi added the enhancement New feature or request label Jul 20, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @rashidi, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new, self-contained example project that illustrates the integration of Spring Data Redis for caching within a Spring Boot application. It provides a practical demonstration of configuring Redis as a cache manager and leveraging Spring's @Cacheable annotation on Spring Data JPA repositories, complete with robust testing using Testcontainers.

Highlights

  • New Example Module: I've added a new Gradle module named data-redis-cache to demonstrate how to implement caching using Spring Data Redis with Spring Boot and Spring Data JPA.
  • Caching Configuration: The new module includes a CacheConfiguration class that enables Spring's caching mechanism and configures RedisCacheManager to use Redis as the caching store.
  • Cacheable Repository Methods: I've applied @Cacheable annotations to findAll() and findById() methods within the CustomerRepository to showcase how Spring automatically caches method results, improving performance for repeated queries.
  • Testcontainers Integration: The example includes comprehensive integration tests using Testcontainers for both PostgreSQL (for the JPA entity) and Redis, ensuring the caching setup works as expected in a realistic environment.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The code changes introduce a new module demonstrating caching with Spring Data Redis. The review includes fixes for the Customer entity's equals and hashCode methods to prevent NullPointerExceptions and ensure correctness with collections. Improvements to the test implementation for better robustness and maintainability have also been suggested.


@Override
public final boolean equals(Object o) {
return o instanceof Customer another && this.id.equals(another.id);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This implementation will throw a NullPointerException if this.id is null, which is the case for a new entity before it's persisted. You should add a null-check for the id before calling .equals() on it to prevent this.

Suggested change
return o instanceof Customer another && this.id.equals(another.id);
return o instanceof Customer another && id != null && id.equals(another.id);


@Override
public int hashCode() {
return id.hashCode();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This hashCode implementation will throw a NullPointerException if id is null. Furthermore, for JPA entities with generated IDs, the hash code will change after the entity is persisted. This can cause issues if the entity is stored in a HashSet or as a key in a HashMap.

A common and safer practice is to use a constant hash code that doesn't depend on the generated ID, ensuring the hash code is stable throughout the entity's lifecycle.

Suggested change
return id.hashCode();
return getClass().hashCode();


@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
return RedisCacheManager.create(connectionFactory);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The RedisCacheManager.create() method has been deprecated since Spring Framework 6.1. It's recommended to use the builder pattern, which provides more flexibility for configuration.

Suggested change
return RedisCacheManager.create(connectionFactory);
return RedisCacheManager.builder(connectionFactory).build();

@DisplayName("Given the method name is configured as the cache's key Then subsequent retrieval should return the same value as initial retrieval")
void findAll() {
var persisted = customers.findAll();
var cached = caches.getCache("customers").get("findAll").get();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly chaining .get() can lead to a NullPointerException if the cache entry for the key "findAll" does not exist, as caches.getCache("customers").get("findAll") would return null. This can make test failures harder to diagnose.

A more robust approach would be to verify the ValueWrapper is not null before getting its value.

@DisplayName("Given the cache is configured Then subsequent retrieval with the same key should return the same value as initial retrieval")
void findById() {
var persisted = customers.findById(1L).get();
var cached = caches.getCache("customerById").get(1L).get();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly chaining .get() can lead to a NullPointerException if the cache entry for the key 1L does not exist, as caches.getCache("customerById").get(1L) would return null. This can make test failures harder to diagnose.

A more robust approach would be to verify the ValueWrapper is not null before getting its value.

@rashidi rashidi merged commit 657fec5 into master Jul 20, 2025
5 checks passed
@rashidi rashidi deleted the spring-data-jpa-redis branch July 20, 2025 12:48
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
66.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant