Spring Boot 2.X: Spring Cache

Keywords: Programming Spring Mybatis Java SpringBoot

Introduction to Spring Cache

Multi-Cache support is introduced in Spring 3.1. In the spring-context package, two interfaces, org.spring framework.cache.Cache and org.spring framework.cache.CacheManager, are defined to unify different caching technologies. Cache interfaces include common operations of caching: add, delete, read, and so on. CacheManager is an abstract interface for Spring caches. Common Cache Managers supported by Spring are as follows:

CacheManager describe
SimpleCacheManager Use a simple Collection to store caches
ConcurrentMapCacheManager Implementing caching using java.util.Concurrent HashMap
NoOpCacheManager Testing only, no caching is actually stored
EhCacheCacheManger EhCache is used as the cache technology. EhCache is a pure Java in-process caching framework with fast and lean features. It is the default CacheProvider in Hibernate and the most widely used cache in Java.
JCacheCacheManager Implementation of JCache (JSR-107) standard as a caching technology
CaffeineCacheManager Caffeine is used as the cache technology. Used to replace Guava caching technology.
RedisCacheManager Using Redis as Caching Technology
HazelcastCacheManager Using Hazelcast as Caching Technology
CompositeCacheManager For composite Cache Managers, you can poll from multiple Cache Managers to get the corresponding cache

Spring Cache provides @Cacheable,@CachePut,@CacheEvict,@Caching and other annotations, which are used in the method. By annotating Cache, we can apply the same transaction-like caching logic transparently to our business code, and only need less code. Core idea: When we call a method, we store the parameters of the method and the most key-value pair of the returned results in the cache. When we call the method with the same parameters next time, we will not execute it again, but get the results directly from the cache and return them.

Cache annotation

1.@EnableCaching

Open the caching function, usually on the startup class.

2.@CacheConfig

When we need to cache more and more places, you can use the @CacheConfig(cacheNames = {"cacheName"} annotation to uniformly specify the value above the class, then omit the value, if you still write the value in your method, then the value of the method is still the standard.

3.@Cacheable

According to the method, the returned results are cached. The next request, if the cache exists, the cached data is directly read and returned. If the cache does not exist, the method is executed and the returned results are stored in the cache. Generally used in query methods. Look at the source code, the attribute values are as follows:

Property/Method Name explain
value Cache name, mandatory, which specifies where your cache is stored in the namespace
cacheNames Just like value, choose one or the other.
key Optional properties, you can customize the cached key using the SpEL tag
keyGenerator Generator of key. key/keyGenerator Optional Use
cacheManager Specify a cache manager
cacheResolver Specify a fetch parser
condition Caching if conditions are met
unless Conditions are met without caching
sync Whether to use asynchronous mode, default to false

4.@CachePut

Using this annotation flag, it executes each time and stores the results in the specified cache. Other methods can read the cached data directly from the response cache without querying the database. Usually used in new methods. Look at the source code, the attribute values are as follows:

Property/Method Name explain
value Cache name, mandatory, which specifies where your cache is stored in the namespace
cacheNames Just like value, choose one or the other.
key Optional properties, you can customize the cached key using the SpEL tag
keyGenerator Generator of key. key/keyGenerator Optional Use
cacheManager Specify a cache manager
cacheResolver Specify a fetch parser
condition Caching if conditions are met
unless Conditions are met without caching

5.@CacheEvict

The method using this annotation flag clears the specified cache. Usually used for updating or deleting methods Look at the source code, the attribute values are as follows:

Property/Method Name explain
value Cache name, required, which specifies the namespace where your cache is stored
cacheNames Just like value, choose one or the other.
key Optional properties, you can customize the cached key using the SpEL tag
keyGenerator Generator of key. key/keyGenerator Optional Use
cacheManager Specify a cache manager
cacheResolver Specify a fetch parser
condition Cache if conditions are met
allEntries Whether to empty all caches, default is false. If specified as true, all caches are cleared immediately after method invocation
beforeInvocation Whether to empty before method execution, default is false. If specified as true, the cache is emptied before the method executes

6.@Caching

This annotation enables multiple annotations to be used simultaneously on the same method. It can be seen from its source code that:

public @interface Caching {

	Cacheable[] cacheable() default {};

	CachePut[] put() default {};

	CacheEvict[] evict() default {};

}

Spring Cache uses

1. Build projects and add dependencies

<?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>2.1.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.zwqh</groupId>
	<artifactId>spring-boot-cache</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-cache</name>
	<description>spring-boot-cache</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- Spring Cache -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>
		<!-- jdbc -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

		<!-- Hot Deployment Module -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional> <!-- This needs to be true Hot Deployment Is Effective -->
		</dependency>


		<!-- mysql Database Driver. -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<!-- mybaits -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.0</version>
		</dependency>
		
	</dependencies>

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

</project>

2.application.properties configuration file

#datasource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=UTF-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
#mybatis
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml

3. entity class

public class UserEntity implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 5237730257103305078L;
	private Long id;
	private String userName;
	private String userSex;
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserSex() {
		return userSex;
	}
	public void setUserSex(String userSex) {
		this.userSex = userSex;
	}
	
}

4. Data layer dao and mapper.xml

public interface UserDao {
	//mapper.xml 
	/**
	 * Get all users
	 * @return
	 */
	List<UserEntity> getAll();
	/**
	 * Getting users based on id
	 * @return
	 */
	UserEntity getOne(Long id);
	/**
	 * New users
	 * @param user
	 */
	void insertUser(UserEntity user);
	/**
	 * Modify user
	 * @param user
	 */
	void updateUser(UserEntity user);
	/**
	 * delete user
	 * @param id
	 */
	void deleteUser(Long id);
		

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.zwqh.springboot.dao.UserDao">
	<resultMap type="cn.zwqh.springboot.model.UserEntity" id="user">
		<id property="id" column="id"/>
		<result property="userName" column="user_name"/>
		<result property="userSex" column="user_sex"/>
	</resultMap>
	<!-- Get all users -->
	<select id="getAll" resultMap="user">
		select * from t_user
	</select>
	<!-- According to users ID Get users -->
	<select id="getOne" resultMap="user">
		select * from t_user where id=#{id}
	</select>
	<!-- New users -->
	<insert id="insertUser" parameterType="cn.zwqh.springboot.model.UserEntity">
		insert into t_user (user_name,user_sex) values(#{userName},#{userSex})
	</insert>
	<!-- Modify user -->
	<update id="updateUser" parameterType="cn.zwqh.springboot.model.UserEntity">
		update t_user set user_name=#{userName},user_sex=#{userSex} where id=#{id}
	</update>
	<!-- delete user -->
	<delete id="deleteUser" parameterType="Long">
		delete from t_user where id=#{id}
	</delete>
</mapper>


5. Business Code Layer Interface Service and Implementation Class Service Impl

public interface UserService {

	/**
	 * Find all
	 * @return
	 */
	List<UserEntity> getAll();
	/**
	 * Getting users based on id
	 * @param id
	 * @return
	 */
	UserEntity getOne(Long id);
	/**
	 * New users
	 * @param user
	 */
	void insertUser(UserEntity user);
	/**
	 * Modify user
	 * @param user
	 */
	void updateUser(UserEntity user);
	
	void deleteAll1();
	
	void deleteAll12();
}

@Service
@CacheConfig(cacheNames = {"userCache"})
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDao userDao;

	@Override
	@Cacheable("userList") // Flag read cache operation. If the cache does not exist, the target method is called and the result is put into the cache.
	public List<UserEntity> getAll() {
		System.out.println("Cache does not exist, execution method");
		return userDao.getAll();
	}

	@Override
	@Cacheable(cacheNames = { "user" }, key = "#id"// If the cache exists, read the cache value directly; if the cache does not exist, call the target method and put the result into the cache
	public UserEntity getOne(Long id) {
		System.out.println("Cache does not exist, execution method");
		return userDao.getOne(id);
	}

	@Override
	@CachePut(cacheNames = { "user" }, key = "#User.id"// Write cache, key is user.id, which is usually annotated on the new method.
	public void insertUser(UserEntity user) {
		System.out.println("Write cache");
		userDao.insertUser(user);
	}

	@Override
	@CacheEvict(cacheNames = { "user" }, key = "#user.id ")// Clear the cache according to key, which is usually annotated on modification and deletion methods
	public void updateUser(UserEntity user) {
		System.out.println("Clear cache");
		userDao.updateUser(user);
	}
	
	@Override
    @CacheEvict(value="userCache",allEntries=true)//Clear all caches after method invocation
    public void deleteAll1() {
	
	}
	
	@Override
    @CacheEvict(value="userCache",beforeInvocation=true)//Clear all caches before method calls
    public void deleteAll2() {

    }

}

6. Testing Controller

@RestController
@RequestMapping("/user")
public class UserController {

	@Autowired
	private UserService userService;

	/**
	 *  Find all
	 * @return
	 */
	@RequestMapping("/getAll")
	public List<UserEntity> getAll(){
		return userService.getAll(); 
	}
	/**
	 * Getting users based on id
	 * @return
	 */
	@RequestMapping("/getOne")
	public UserEntity getOne(Long id){
		return userService.getOne(id); 
	}
	/**
	 * New users
	 * @param user
	 * @return
	 */
	@RequestMapping("/insertUser")
	public String insertUser(UserEntity user) {
		userService.insertUser(user);
		return "insert success";
	}	
	/**
	 * Modify user
	 * @param user
	 * @return
	 */
	@RequestMapping("/updateUser")
	public String updateUser(UserEntity user) {
		userService.updateUser(user);
		return "update success";
	}
}

7. Start Cache

@SpringBootApplication
@MapperScan("cn.zwqh.springboot.dao")
@EnableCaching //Start Cache function
public class SpringBootCacheApplication {

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

}

8. Database and test data

The database and test data are still in use.

9. test

Write unit tests or add corresponding paths and parameters by visiting http://127.0.0.1:8080/user/.

File

org.springframework.cache

Sample code

github

Code cloud

Non-special description, copyright of this article belongs to Foggy and cold All, reproduce please indicate the source.

Title: Spring Boot 2.X(7): Spring Cache

Original address: https://www.zwqh.top/article/info/13

Posted by copernic67 on Mon, 14 Oct 2019 20:00:28 -0700