1.使用Service层来实现缓存
从软件设计的角度分析,service层是业务逻辑层,dao层是数据接入层,dao层的功能比较单一,在service层中出现复杂业务的时候(调用多个dao层方法时),此时dao缓存就无法满足系统要求,需在将缓存提升到service层,可以获取更加丰富的缓存数据。
2.spring实现缓存步骤
2.1 实现springcache
mybatis的cache接口,需要自己实现
spring的cache接口,不需要自己实现,因为springboot中自带的有实现类(org.springframework.data.redis.cache.RedisCache)
2.2 开启缓存
1.添加配置
#redis服务器的IP地址
spring.redis.host=192.168.145.168
#redis的端口号
spring.redis.port=6379
#缓存的类型
spring.cache.type=redis
#缓存的命名空间
spring.cache.cache-names=xxxCache
2.缓存注解开启
- 在启动类上加上注解,@enableCaching
//开启缓存,开启mybatis扫描
@SpringBootApplication
@EnableCaching
public class SpringCacheApplication {
- 在业务类上添加缓存的注解,@CacheConfig标识本类使用的缓存名称
//开启注解
@Service("questionService")
@CacheConfig(cacheNames = "xxxCache")
public class QuestionServiceImpl implements QuestionService {
-
@Cacheable加载方法上,标识某个方法的返回值进行缓存
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
@Cacheable
@Override
public Question queryById(Integer id) {
return this.questionDao.queryById(id);
}
@Cacheable
@Override
public List<Question> finAll() {
return questionDao.finAll();
}
保存和更新时的缓存操作
/**
* 新增数据
*
* @param question 实例对象
* @return 实例对象
* 添加热点数据,想立即放入缓存,可以在insert方法上使用CachePut,
* 并且cacheput能够更新之前的缓存
*/
@CachePut(key = "#question.id")
//可以使用root对象,获取相关名称作为key
/* @CachePut(key = "#root.targetClass+#question.id")*/
@Override
public Question insert(Question question) {
this.questionDao.insert(question);
return question;
}
/**
* 修改数据
*
* @param question 实例对象
* @return 实例对象
*/
@CachePut(key = "#question.id")
@Override
public Question update(Question question) {
this.questionDao.update(question);
return this.queryById(question.getId());
}
@CachePut(key = "#root.methodName+#question.id") | root通过methodName获取方法名 | xxxCache::insert50 |
@CachePut(key = "#root.target+#question.id") | root通过target获取调用对象 | xxxCache::com.yun.service.impl.QuestionServiceImpl@6cc2242751 |
@CachePut(key = "#root.targetClass+#question.id") | root通过targetClass获取方法所属的类的全路径 | xxxCache::class com.yun.service.impl.QuestionServiceImpl53 |
删除操作,@CacheEvict(key = "#id")
上面操作会出现两个问题:
问题一:新加数据之后,查询所有的缓存没有刷新。
问题二:删除数据之后,查询所有的缓存没有刷新。
解决办法:以使用CacheEvict注解指定allentries=true来解决。
beforeInvocation true 先删除缓存
allEntries true 删除命名空间下的所有的缓存
完整代码如下:
//开启注解
@Service("questionService")
@CacheConfig(cacheNames = "zykCache")
public class QuestionServiceImpl implements QuestionService {
@Resource
private QuestionDao questionDao;
/**
* 通过ID查询单条数据
*
* @param id 主键
* @return 实例对象
*/
//打开注解
@Cacheable
@Override
public Question queryById(Integer id) {
return this.questionDao.queryById(id);
}
//打开缓存注解
@Cacheable
@Override
public List<Question> queryAll() {
return this.questionDao.queryAll();
}
/**
* 分页查询
*
* @param question 筛选条件
* @param pageRequest 分页对象
* @return 查询结果
*/
@Override
public Page<Question> queryByPage(Question question, PageRequest pageRequest) {
long total = this.questionDao.count(question);
return new PageImpl<>(this.questionDao.queryAllByLimit(question, pageRequest), pageRequest, total);
}
/**
* 新增数据
* 添加热点数据,想立即放入缓存,可以在insert方法上使用CachePut
* @param question 实例对象
* @return 实例对象
*/
// @CachePut(key = "#root.methodName+'_'+#question.id")
//#root.target调用对象 #root.targetClass获取类的全路径
//@CachePut(key = "#root.targetClass+'_'+#question.id")
@CacheEvict(key = "#question.id",allEntries = true,beforeInvocation = false)
@Override
public Question insert(Question question) {
this.questionDao.insert(question);
return question;
}
/**
* 修改数据
*
* @param question 实例对象
* @return 实例对象
*/
//@CachePut(key = "#question.id")
@CacheEvict(key = "#question.id",allEntries = true,beforeInvocation = false)
@Override
public Question update(Question question) {
this.questionDao.update(question);
return this.queryById(question.getId());
}
/**
* 通过主键删除数据
*allEntries = true 删除命名空间下的所有缓存
*beforeInvocation = true 先删除缓存
* @param id 主键
* @return 是否成功
*/
@CacheEvict(key = "#id",allEntries = true,beforeInvocation = false)
@Override
public boolean deleteById(Integer id) {
return this.questionDao.deleteById(id) > 0;
}
}
以上就是开启Springboot缓存到Redis的过程!