接着修改1166057546,/tesla?id=1166057546&name=TeslaRoadster&price=1600000&vehicleType=roaster&factoryId=3,修改也是成功的
再次查询1166057546
此时发现查询到的结果还是之前的结果,并不是更新后的结果,这是因为更新没有返回数据,方法中都是void,所以缓存中的数据没有变化
依次修改TeslaService接口、TeslaServiceImpl类以及TeslaController中的update方法,使方法返回更新后的数据
Tesla updateTesla(Tesla tesla); 复制代码
@Override @Cacheable(cacheNames = {"tesla"}, keyGenerator = "lilithKeyGenerator" public Tesla updateTesla(Tesla tesla) { log.info(tesla.getId() + "被更新了"); return tesla; } 复制代码
@GetMapping("/tesla") public Tesla update(Tesla tesla){ Tesla updateTesla = teslaService.updateTesla(tesla); return updateTesla; } 复制代码
重新启动应用,在浏览器中查询116605754
更新116605754
再次查询116605754
控制台返回的仍是第一次查询时保存的数据
这一次是因为查询结果存储时使用的key是id,更新结果存储时使用的key是employee对象,统一key 再次测试,都是用id作为key,只需要修改TeslaServiceImpl中的updateTesla()
@CachePut(cacheNames = {"tesla"}, key = "#tesla.id") 复制代码
重启应用,再次查询
进行更新操作
再次查询
更新后再次查询时返回的数据是更新后的数据
使用@CachePut需要注意的事项:
- 更新后要将更新的数据返回
- 要将查询时保存的key和更新时设置的key保持一致,这样才会更新缓存
@CacheEvict
该注解的作用是用来清除缓存
分别在TeslaService接口、TeslaServiceImpl实现类以及TeslaController中增加方法
void deleteTeslaCache(Integer id); 复制代码
@CacheEvict(cacheNames = {"tesla"}, key = "#id") public void deleteTeslaCache(Integer id){ log.info("清除" + id + "的缓存"); } 复制代码
@GetMapping("/tesla/delcache/{id}") public void deleteCache(@PathVariable("id") Integer id){ teslaService.deleteTeslaCache(id); } 复制代码
/tesla/delcache/1166057546
allEntries属性
该属性是会删除缓存中所有的数据,默认是清除指定cacheNames的缓存
beforeInvocation属性
该属性是指在方法执行前删除缓存还是方法执行后删除缓存,为布尔值类型,默认为false既在方法执行后删除缓存
@CacheEvict(cacheNames = {"tesla"}, key = "#id") public void deleteTeslaCache(Integer id){ log.info("清除" + id + "的缓存"); // 增加异常代码 int i = 1 / 0; } 复制代码
重启
再次查询,没有调用SQL语句,方法由于出现异常,导致未能执行清除缓存
@CacheEvict(cacheNames = {"tesla"}, key = "#id", beforeInvocation = true) 复制代码
再次查询还是执行了SQL语句,说明在方法执行前就已经将缓存删除,方法中的异常不会对清除缓存造成影响
@Caching
该注解用来指定多个复杂规则
分别在TeslaController、TeslaService、TeslaServiceImpl、TeslaMapper以及TeslaMapper.xml中增加代码及SQL语句,按照name来查询
@GetMapping("/tesla/name/{name}") public Tesla findByName(@PathVariable("name") String name){ return teslaService.getTeslaByName(name); } 复制代码
Tesla getTeslaByName(String name); 复制代码
public Tesla getTeslaByName(String name){ log.info("根据" + name + "查询特斯拉"); return teslaMapper.selectOneByName(name); } 复制代码
Tesla selectOneByName(String name); 复制代码
<select id="selectOneByName" resultType="tesla"> SELECT <include refid="Base_Columns_List" /> FROM tesla WHERE name = #{name} </select> 复制代码
在TeslaServiceImpl的getTeslaByName()方法上增加@Caching注解,该注解中配置了一个@Cacheable注解和一个@CachePut注解
@Caching( cacheable = { @Cacheable(cacheNames = "tesla", key = "#name") }, put = { @CachePut(cacheNames = "tesla", key = "#result.id"), } ) 复制代码
重新应用,首先按照name查询 /tesla/name/TeslaRoadster,控制台打印出SQL
接着按照id查询 /tesla/1166057546,此时已经有缓存了,没有执行SQL语句
再次按照name查询,控制台打印出SQL语句
再用name查询,还是会执行SQL,因为getTeslaByName()方法有@CachePut注解,这个注解就表示一定要执行方法
CacheConfig
@CacheConfig注解标注在类上,可以定义一些公共的缓存配置,比如cacheNames、key等
在TeslaServiceImpl类上增加@CacheConfig,配置cacheNames
@CacheConfig(cacheNames = "tesla") 复制代码
将getTeslaByName()方法上@Caching标注的cacheNames属性删除
@Caching( cacheable = { @Cacheable(key = "#name") }, put = { @CachePut(key = "#result.id"), } ) 复制代码
重新启动应用,首先按照name查询/tesla/name/TeslaRoadster,控制台打印出SQL
接着按照id查询
再次按照name查询
控制台输出结果与单独配置cacheNames时输出的结果一致