以注解的方式使用redis缓存得用法@CachePut , @CacheEvict, @Cacheable

第一步:在启动类加注解@EnableCaching

@SpringBootApplication
@EnableCaching
//@MapperScan(basePackages = "com.imooc.dataobject.mapper")

public class SellApplication {

    public static void main(String[] args) {
        SpringApplication.run(SellApplication.class, args);
    }
}

第二部:在相应的需要缓存的类里面加个注解,测试一下

以注解的方式使用redis缓存得用法@CachePut , @CacheEvict, @Cacheable_第1张图片

然后果然不出所料,一大堆错误和坑,一起来看看,原来是Serializable的错误

java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.imooc.VO.ResultVO]

Hibernate: select productcat0_.category_id as category1_2_, productcat0_.category_name as category2_2_, productcat0_.category_type as category3_2_, productcat0_.create_time as create_t4_2_, productcat0_.update_time as update_t5_2_ from product_category productcat0_ 
	arializationRedisSerializer.java:91)
	at org.springframework.data.redis.cache.RedisCache$CacheValueAccessor.convertToBytesIfNecessary(RedisCache.java:471)

解决错误的办法就是加序列化public class ResultVO implements Serializable

可以给每一个都这样操作

@Data
public class ResultVO implements Serializable {
    //自己瞎写了一个
    private static final long serialVersionUID = 222343234234L;
    //resultVO  类自己的属性
    private Integer code;
    private String msg;

    //保存具体内容,是个对象,泛型实现。
    private T data;
}

然后再类里面生成ID,需要用到一下这个插件,在idea里下载,重启即可

以注解的方式使用redis缓存得用法@CachePut , @CacheEvict, @Cacheable_第2张图片

然后运行,可以看到一件成功显示数据,再打开Redis客户端,可以看到有product的一条数据,

然后你不断的刷新,都不会再进入那个方法,因为直接从缓存中拿到这个序列化存储的对象,

以注解的方式使用redis缓存得用法@CachePut , @CacheEvict, @Cacheable_第3张图片

但是这里有一个很严重的问题,你把数据库的信息改了,然后刷新页面,还是原来的数据,这就是因为缓存的原因,所以我们给save更新的方法也要加个更新的处理, 接口方式。如图。

  @PostMapping("/save")
    @CachePut(cacheNames = "product", key = "123")
    public ModelAndView save(@Valid ProductForm productForm,
                             BindingResult bindingResult,
                             Map map){

        // 1 先验证提交过来的表单有无错误信息 -- 有 -- 跳转错误页面
        if(bindingResult.hasErrors()){
            map.put("msg", bindingResult.getFieldError().getDefaultMessage());
            map.put("url", "/sell/seller/product/list");
            return new ModelAndView("common/error", map);
        }
        ProductInfo productInfo = new ProductInfo();

//        if(productForm.getProductId() != null){
//            productForm.setProductId(KeyUtil.genUniqueKey());
//        }

        // 2 没有错误, 拷贝表单信息 为 商品信息格式,
        // 为了完整 -- 提前查好, 弄好默认值
        //    然后存储 -- 调用service 层方法   -- 出错处理
        try{

            /** 这里必须判断 是新增 还是 修改, 有几个特定的属性需要单独赋值处理
             *  如果productId为空, 说明是新增  -- 不是新增:查找。 是新增:设置ID。
             * ************** 新增和增加的 关键点核心 *****************
             */
            if(!StringUtils.isEmpty(productForm.getProductId())){
                productInfo = productInfoService.findOne(productForm.getProductId());
            }else{
                productForm.setProductId(KeyUtil.genUniqueKey());
            }
            BeanUtils.copyProperties(productForm, productInfo);
            productInfoService.save(productInfo);
        }catch (SellException e){
            map.put("msg", e.getMessage());
            map.put("url", "/sell/seller/product/list");
            return new ModelAndView("common/error", map);
        }
        map.put("msg", ResultEnum.SUCCESS.getMessage());
        map.put("url", "/sell/seller/product/list");
        return new ModelAndView("common/success", map);


    }

但是这样会报错,因为更新时候返回的是ModelandView对象, 而前面我们保存的是resultVO,对象不同,显然报错,所以改用另一种方法, 用一种注解代替

//    @CachePut(cacheNames = "product", key = "123")
    @CacheEvict(cacheNames = "product", key = "123")

    @CacheEvict(cacheNames = "product", key = "123")就代表来的时候执行这个方法,执行完之后把结果从Redis中驱赶出去,也就是删除,当再次访问查询时候,Redis中没有这个数据,再次数据库查询 -- 从而达到更新的目的。

以上讲的是基本用法,Redis的知识很丰富,持续关注

cacheNames = "product", key = "123",

其实这两个值应该是动态变化的,例如这样,   

@CachePut(cacheNames = "product", key = "#productId")
    public ProductInfo findOne(String productId) 

这个叫做skel表达式

    @Override
    @CachePut(cacheNames = "product", key = "#productId")
    public ProductInfo findOne(String productId) {
        return repository.findOne(productId);
    }

 

注意点:

@CacheConfig(cacheNames = "product")

1. cacheNames = "product", key = "123",这两个必须写,

   @CachePut(cacheNames = "product", key = "#productId",
            condition="#productId.length() > 3" ,
    unless = "#result.getCode() != 0")

这些都是他的扩展用法,具体不在讲述,我只体现框架概念。

你可能感兴趣的:(Java实战技术栏,Java)