@Cacheable缓存注解:
@Service
@CacheConfig(cacheNames = "person") //将cacheNames抽取出来
public class PersonService {
@Autowired
PersonDao personDao;
/*1. @Cacheable的几个属性详解:
* cacheNames/value:指定缓存组件的名字
* key:缓存数据使用的key,可以用它来指定。默认使用方法参数的值,一般不需要指定
* keyGenerator:作用和key一样,二选一
* cacheManager和cacheResolver作用相同:指定缓存管理器,二选一
* condition:指定符合条件才缓存,比如:condition="#id>3"
* 也就是说传入的参数id>3才缓存数据
* unless:否定缓存,当unless为true时不缓存,可以获取方法结果进行判断
* sync:是否使用异步模式*/
//@Cacheable(cacheNames= "person")
//@Cacheable(cacheNames= "person",key="#id",condition="#id>3")
@Cacheable(key="#id")
public Person queryPersonById(Integer id){
System.out.println("查询"+id+"号员工信息");
Person person=new Person();
person.setId(id);
return personDao.query(person);
}
/**
* @CachePut:即调用方法,又更新缓存数据
* 修改了数据库中的数据,同时又更新了缓存
*
*运行时机:
* 1.先调用目标方法
* 2.将目标方法返回的结果缓存起来
*
* 测试步骤:
* 1.查询1号的个人信息
* 2.以后查询还是之前的结果
* 3.更新1号的个人信息
* 4.查询一号员工返回的结果是什么?
* 应该是更新后的员工
* 但只更新了数据库,但没有更新缓存是什么原因?
* 5.如何解决缓存和数据库同步更新?
* 这样写:@CachePut(cacheNames = "person",key = "#person.id")
* @CachePut(cacheNames = "person",key = "#result.id")
*/
@CachePut(key = "#result.id")
public Person updatePerson(Person person){
System.out.println("修改"+person.getId()+"号员工信息");
personDao.update(person);
return person;
}
/**
* @CacheEvict:清除缓存
* 1.key:指定要清除缓存中的某条数据
* 2.allEntries=true:删除缓存中的所有数据
* beforeInvocation=false:默认是在方法之后执行清除缓存
* 3.beforeInvocation=true:现在是在方法执行之前执行清除缓存,
* 作用是:只清除缓存、不删除数据库数据
*/
//@CacheEvict(cacheNames = "person",key = "#id")
@CacheEvict(cacheNames = "person",allEntries=true)
public void deletePerson(Integer id){
System.out.println("删除"+id+"号个人信息");
//删除数据库数据的同时删除缓存数据
//personDao.delete(id);
/**
* beforeInvocation=true
* 使用在方法之前执行的好处:
* 1.如果方法出现异常,缓存依旧会被删除
*/
//int a=1/0;
}
/**
* @Caching是 @Cacheable、@CachePut、@CacheEvict注解的组合
* 以下注解的含义:
* 1.当使用指定名字查询数据库后,数据保存到缓存
* 2.现在使用id、age就会直接查询缓存,而不是查询数据库
*/
@Caching(
cacheable = {@Cacheable(key="#name")},
put={ @CachePut(key = "#result.id"),
@CachePut(key = "#result.age")
}
)
public Person queryPersonByName(String name){
System.out.println("查询的姓名:"+name);
return personDao.queryByName(name);
}
}
使用Redis缓存:
ServiceImpl类
package com.szh.springboot_redis.service.impl;
import com.szh.springboot_redis.mapper.StudentMapper;
import com.szh.springboot_redis.pojo.Students;
import com.szh.springboot_redis.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudnetServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Autowired
private RedisTemplate redisTemplate;
/**
* 查询所有信息
*/
@Override
public List<Students> findAllStudnet() {
String key = "student";
ValueOperations<String, List<Students>> operations = redisTemplate.opsForValue();
// 缓存存在
boolean hasKey = redisTemplate.hasKey(key);
if (hasKey) {
List<Students> students = operations.get(key);
return students;
}else {
// 从 DB 中获取城市信息
List<Students> students = studentMapper.findAllStudnet();
// 插入缓存
operations.set(key, students);
return students;
}
}
/**
* 根据id查询信息
*/
@Override
public Students findStudentById(Integer id) {
String key = "city_" + id;
ValueOperations<String, Students> operations = redisTemplate.opsForValue();
// 缓存存在
boolean hasKey = redisTemplate.hasKey(key);
if (hasKey) {
Students students = operations.get(key);
return students;
}else {
// 从 DB 中获取城市信息
Students students = studentMapper.findStudentById(id);
// 插入缓存
operations.set(key, students);
return students;
}
}
/**
* 删除指定信息
*/
@Override
public int delStudent(Integer id) {
int ret = studentMapper.delStudent(id);
// 缓存存在,删除缓存
String key = "studnet_" + id;
boolean hasKey = redisTemplate.hasKey(key);
if (hasKey) {
redisTemplate.delete(key);
}
return ret;
}
/**
* 修改指定信息
*/
@Override
public int updateStudent(Students students) {
int ret = studentMapper.updateStudent(students);
// 缓存存在,删除缓存
String key = "students_" + students.getSid();
boolean hasKey = redisTemplate.hasKey(key);
if (hasKey) {
redisTemplate.delete(key);
}
return ret;
}
}
修改springboot中redis配置中的修改RedisTemplate 默认的序列化规则,将缓存序列化。
配置config文件
RedisConfig.java类:
package com.szh.springboot_redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig{
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
当缓存不是对象时:
就直接自动注入StringRedisTemplate然后调用属性方法
@Autowired
private StringRedisTemplate StringRedisTemplate;//K-V操作字符串
@Autowired
private RedisTemplate redisTemplate;//K-V都是对象
StringRedisTemplate.opsForValue();//操作字符串
StringRedisTemplate.opsForList();//操作集合
public String test(){
//给redis中保存数据
StringRedisTemplate.opsForValue().append("msg","hello");//存入字符串
StringRedisTemplate.opsForValue().get("msg");//从缓存中获取值
StringRedisTemplate.opsForList().leftPush("mylist","1");//存入集合
StringRedisTemplate.opsForList().leftPush("mylist","2");
//测试保存对象
//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
//RedisTemplate.opsForValue().set("emp-01",Object);注意要序列化
/*1、将数据以json的方式保存
redisTemplate默认的序列化规则;改变默认的序列化规则
*/
redisTemplate.opsForValue().set("Student",Object);
}