从软件设计的角度分析,service层是业务逻辑层,dao层是数据接入层,dao层的功能比较单一,在service层中出现复杂业务的时候(调用多个dao层方法时),此时dao缓存就无法满足系统要求,需在将缓存提升到service层,可以获取更加丰富的缓存数据。
mybatis的cache接口,需要自己实现
spring的cache接口,不需要自己实现,因为springboot中自带的有实现类(org.springframework.data.redis.cache.RedisCache)
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.缓存注解开启
//开启缓存,开启mybatis扫描 @SpringBootApplication @EnableCaching public class SpringCacheApplication {
//开启注解 @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的过程!