Boost Spring Boot Performance: A Step‑by‑Step Guide to Adding Caching with Annotations

This tutorial explains why caching is essential for growing Spring Boot applications, walks through adding Spring's annotation‑based cache support to an existing Spring Data JPA project, and details the key cache annotations, configuration steps, and observable performance improvements.

Programmer DD
Programmer DD
Programmer DD
Boost Spring Boot Performance: A Step‑by‑Step Guide to Adding Caching with Annotations

As an application’s user base grows, database queries can become a performance bottleneck; using a cache is an effective way to alleviate this. Since Spring 3, annotation‑based caching is available, and Spring Boot provides auto‑configuration to enable it with minimal effort.

Quick Start

The example builds on a previous tutorial that uses Spring Data JPA to access a MySQL User table. The User entity is defined as:

@Entity
@Data
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private Integer age;
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

The repository interface looks like:

public interface UserRepository extends JpaRepository<User, Long> {
    User findByName(String name);
    User findByNameAndAge(String name, Integer age);
    @Query("from User u where u.name=:name")
    User findUser(@Param("name") String name);
}

First, enable SQL logging by adding spring.jpa.show-sql=true (or the equivalent Hibernate property for Spring Boot 1.x) to application.properties, then insert a test record and query it twice:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter51ApplicationTests {
    @Autowired
    private UserRepository userRepository;
    @Test
    public void test() throws Exception {
        userRepository.save(new User("AAA", 10));
        User u1 = userRepository.findByName("AAA");
        System.out.println("First query: " + u1.getAge());
        User u2 = userRepository.findByName("AAA");
        System.out.println("Second query: " + u2.getAge());
    }
}

Before adding caching, both queries generate a select statement, as shown in the console output.

Introducing Cache

1. Add the cache starter dependency to pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2. Enable caching in the main application class with @EnableCaching:

@EnableCaching
@SpringBootApplication
public class Chapter51Application {
    public static void main(String[] args) {
        SpringApplication.run(Chapter51Application.class, args);
    }
}

3. Configure the repository to use a cache named users and mark the query method as cacheable:

@CacheConfig(cacheNames = "users")
public interface UserRepository extends JpaRepository<User, Long> {
    @Cacheable
    User findByName(String name);
}

Running the test again shows that the second call to findByName no longer triggers a SQL query, confirming that the result was retrieved from the cache.

Injecting CacheManager into the test and inspecting the users cache reveals the cached User object after the first query.

CacheManager view
CacheManager view

Cache Annotation Details

@CacheConfig

: defines common cache settings for the class, e.g., cacheNames = "users". @Cacheable: caches the method result; key defaults to all method parameters. Important attributes: value / cacheNames: name of the cache. key: SpEL expression to compute the cache key, e.g., #p0. condition: SpEL condition evaluated before caching; only matching results are cached. unless: SpEL condition evaluated after method execution; prevents caching when true. keyGenerator: custom KeyGenerator implementation (mutually exclusive with key). cacheManager and cacheResolver: specify which manager or resolver to use when multiple are present. @CachePut: always executes the method and updates the cache with the result. @CacheEvict: removes entries from the cache, typically on delete operations. Additional attributes: allEntries: when true, clears the entire cache. beforeInvocation: when true, eviction occurs before the method runs.

Full Example Repository

The complete source code is available in the chapter5-1 directory of the following repositories:

GitHub: https://github.com/dyc87112/SpringBoot-Learning/

Gitee: https://gitee.com/didispace/SpringBoot-Learning/

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

spring-bootSpring Data JPA@Cacheable
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.