Redis实战:黑马点评之商户查询缓存
关于缓存的知识点,我整合在了另一篇文章【Redis】Redis高级:缓存技术与缓存常见问题 之中,这里只解决项目中的代码编写问题,不再讲述有关缓存的知识点
1 添加商户缓存
在现有的代码中,查询商户信息是直接去数据库中进行查询的,由于商户信息是查询比较频繁的数据,因此我们可以为其添上缓存
那么添加缓存应该怎样进行编码呢?标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis。
具体实现代码如下:
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public Result queryById(Long id) {
//查询前先查询缓存
//组装key
String key = RedisConstants.CACHE_SHOP_KEY+id;
//查询缓存信息是否存在
String value = stringRedisTemplate.opsForValue().get(key);
//缓存存在,直接返回缓存信息
if(value != null){
return Result.ok(JSONUtil.toBean(value,Shop.class));
}
//缓存不存在,则查询数据库信息
Shop shop = getById(id);
//数据库中也不存在则报错
if(shop == null){
return Result.fail("商户不存在");
}
//将查询出来的数据缓存在redis中
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop));
//返回查询结果
return Result.ok(shop);
}
}
2 添加商户类型缓存
将商户类型查询的数据也添加进缓存
代码如下:
ShopTypeController
@RestController
@RequestMapping("/shop-type")
public class ShopTypeController {
@Resource
private IShopTypeService typeService;
@GetMapping("list")
public Result queryTypeList() {
return typeService.queryTypeList();
}
}
ShopTypeService
@Service
public class ShopTypeServiceImpl extends ServiceImpl<ShopTypeMapper, ShopType> implements IShopTypeService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public Result queryTypeList() {
//先查询缓存
String value = stringRedisTemplate.opsForValue().get("cache:shopType:list");
//如果缓存不为空则直接返回
if(value != null){
return Result.ok(JSONUtil.toList(value,ShopType.class));
}
//缓存为空则查询数据库
List<ShopType> shopTypeList = query().orderByAsc("sort").list();
//将查询到的信息保存到缓存
stringRedisTemplate.opsForValue().set("cache:shopType:list",JSONUtil.toJsonStr(shopTypeList));
//响应数据
return Result.ok(shopTypeList);
}
}
3 实现数据库与缓存双写一致
为了确保缓存中的数据与数据库中数据的一致性,现修改有关于Shop的业务逻辑,满足下面的需求:
-
需求一:根据id查询店铺时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间
-
需求二:根据id修改店铺时,先修改数据库,再删除缓存
实现需求一:为缓存数据添加过期时间
修改ShopServiceImpl中的代码
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public Result queryById(Long id) {
//查询前先查询缓存
//组装key
String key = RedisConstants.CACHE_SHOP_KEY+id;
//查询缓存信息是否存在
String value = stringRedisTemplate.opsForValue().get(key);
//缓存存在,直接返回缓存信息
if(value != null){
return Result.ok(JSONUtil.toBean(value,Shop.class));
}
//缓存不存在,则查询数据库信息
Shop shop = getById(id);
//数据库中也不存在则报错
if(shop == null){
return Result.fail("商户不存在");
}
//将查询出来的数据缓存在redis中
stringRedisTemplate.opsForValue().set(
key,
JSONUtil.toJsonStr(shop),
RedisConstants.CACHE_SHOP_TTL,
TimeUnit.MINUTES
);
//返回查询结果
return Result.ok(shop);
}
}
实现需求二:当数据更新后,删除缓存数据
首先修改ShopController中的updateShop方法
/**
* 更新商铺信息
* @param shop 商铺数据
* @return 无
*/
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
// 写入数据库
return shopService.updateShop(shop);
}
然后在ShopServiceImpl中编写updateShop方法
/**
* 执行更新操作,更新后应该删除缓存
* @param shop
* @return
*/
@Override
@Transactional
public Result updateShop(Shop shop) {
Long shopId = shop.getId();
if(shopId == null){
return Result.fail("店铺id不能为空");