【Java】Spring:DBマスタをキャッシュで保持してRESTAPIで一覧を取得する

■処理概要

Springの「@EnableCaching」を有効にして、初回DBアクセス時に取得した情報をキャッシュで保持して、2回目以降は、DBにアクセスせずキャッシュを参照するようにする。

なお、アプリ実行中、DBマスタに新規で追加しても再取得はしない方針とする。

AP
AP
DB
DB
1回目
1回目
AP
AP
DB
DB
2回目以降
2回目以降
キャッシュで
保持
キャッシュで 保持
Text is not SVG – cannot display

▼実行環境

実行する環境のJavaのバージョン等を以下の表に記載する。

項目バージョン
Java17
Spring Boot3.4.2

▼pom.xmlの設定

実行するモジュールの「pom.xml」の設定は以下の通り。

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.4.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>master-cache</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>master-cache</name>
	<description>Cache DB master</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>3.0.4</version>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

■DBマスタ情報

サンプルとして使用するマスタ情報は以下とする。
なお、DBはH2を使用する。

・schema.sql

-- サンプルテーブル
CREATE TABLE SAMPLE_MASTER_TABLE (
  id INT NOT NULL PRIMARY KEY,
  data VARCHAR(3)
);

・data.sql

INSERT INTO SAMPLE_MASTER_TABLE VALUES(1, '001');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(2, '002');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(3, '003');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(4, '004');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(5, '005');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(6, '006');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(7, '007');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(8, '008');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(9, '009');
INSERT INTO SAMPLE_MASTER_TABLE VALUES(10, '010');

■クラス図

実行するモジュールのクラス図を以下に示す。

■ディレクトリ構成

実行するモジュールのディレクトリ構成を以下に示す。

■サンプルコード

・MasterCacheApplication
※デフォルトから「@EnableCaching」を追加

package com.example.master_cache;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@EnableCaching
@SpringBootApplication
public class MasterCacheApplication {

	public static void main(String[] args) {
		SpringApplication.run(MasterCacheApplication.class, args);
	}

}

・RestControllerMasterCache

package com.example.master_cache.controller;

import com.example.master_cache.dto.MasterDTO;
import com.example.master_cache.service.RestServiceMasterCache;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class RestControllerMasterCache {

  private final RestServiceMasterCache service;

  @GetMapping("/rest/master")
  public List<MasterDTO> getListMasterDto() {
    return service.selectAll();
  }

}

・RestServiceMasterCache

package com.example.master_cache.service;

import com.example.master_cache.dto.MasterDTO;
import java.util.List;

public interface RestServiceMasterCache {

  public List<MasterDTO> selectAll();
}

・RestServiceMasterCacheImpl

package com.example.master_cache.service;

import com.example.master_cache.dto.MasterDTO;
import com.example.master_cache.repository.MasterCacheRepository;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class RestServiceMasterCacheImpl implements RestServiceMasterCache {

  private final MasterCacheRepository repository;

  @Override
  @Cacheable("master")
  public List<MasterDTO> selectAll() {
    System.out.println("selectAllが呼ばれました!!");
    return repository.find()
        .stream()
        .map(entity -> new MasterDTO(entity.getId(), entity.getData()))
        .collect(Collectors.toList());

  }

}

・MasterCacheRepository

package com.example.master_cache.repository;

import com.example.master_cache.entity.MasterEntity;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MasterCacheRepository {
  
  List<MasterEntity> find();

}

・RestServiceMasterCache

package com.example.master_cache.service;

import com.example.master_cache.dto.MasterDTO;
import java.util.List;

public interface RestServiceMasterCache {

  public List<MasterDTO> selectAll();
}

・MasterDTO

package com.example.master_cache.dto;

import lombok.Value;

@Value
public class MasterDTO {

  int id;
  String data;
}

・MasterEntity

package com.example.master_cache.entity;

import lombok.Value;

@Value
public class MasterEntity {

  int id;
  String data;
}

■実行結果

・初回アクセス時

コンソールログに以下の文言が出力される。

selectAllが呼ばれました!!

・DBマスタ手動追加後のアクセス(2回目以降)

マスタにID=11、DATA=011を追加

再度、アクセスをしても、ID=11、DATA=011は追加されておらず、「selectAllが呼ばれました!!」のログも表示されない。
→DB参照ではなく、キャッシュを参照していることを確認。

■参考

ソース全量は、以下のGitHubを参照。

コメント

タイトルとURLをコピーしました