前言:
首先将一下为什么遇到了这个问题:
平时我们向Redis存入一个对象的时候,为了速度快一点,占的内存也少一点,我们就会把对象存入到Redis的Hash的数据结构中,
然后在Spring中我们用的一般都是RedisTemplate,而这个api向redis的hash结构中存数据,要用到他的redisTemplate.opsForHash().putAll方法 而putAll方法的两个参数分别是键值和 K key, Map extends HK, ? extends HV> m
可见第二个参数是map集合,那么当我们将一个对象转换成Map集合就用到了HuTool的BeanUtil.beanToMap()方法
使用StringRedisTemplateredis
需要转换成的map的各个字段都是String类型!而bean的每个属性的类型各不相同
那么我们就如何在不遍历map的情况下,在转换为map时就直接将字段类型也转换为String
这里我们都知道是toString就行了,那如何toString呢就要用到这个方法重载的第三个参数了 — CopyOptions
以下是我的代码,可以参考一下
Map<String, Object> map = BeanUtil.beanToMap(user,new HashMap<>(),
CopyOptions.create()
.setIgnoreNullValue(true) //设置忽略空值
.setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString()));
stringRedisTemplate.opsForHash().putAll("user:cache:" + user.getid,map);
如果这个对象里面的属性有空值就会报:
java.lang.NullPointerException: null
at com.hmdp.service.impl.ShopServiceImpl.lambda$queryById$0(ShopServiceImpl.java:81) ~[classes/:na]
at cn.hutool.core.bean.copier.CopyOptions.editFieldValue(CopyOptions.java:258) ~[hutool-all-5.7.17.jar:na]
at cn.hutool.core.bean.copier.BeanCopier.lambda$beanToMap$1(BeanCopier.java:233) ~[hutool-all-5.7.17.jar:na]
at java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:608) ~[na:1.8.0_181]
我们可以看到 setIgnoreNullValue(true) 我们设置忽略空值了,但是我们的属性为空的还会报空指针异常,
如果我们的属性值是空, null.toString(),肯定会报空指针呀,那我们设置忽略空值了,为什么还会报空指针异常呢
这里我们去gitee上看作者的回答:
原因:
原文链接在这里,大家可以参考一下:
https://gitee.com/dromara/hutool/issues/I557F3
那么我们该如何解决呢?下面我介绍下作者的解决方法:
解决方法:
简单来说就是在setFieldValueEditor方法的时候,也进行判断一下 空值
参考代码:
Map<String, Object> map = BeanUtil.beanToMap(user,new HashMap<>(),
CopyOptions.create().
setIgnoreNullValue(true)
//.setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString()));
//解决方法:在setFieldValueEditor中也需要判空
.setFieldValueEditor((fieldName,fieldValue) -> {
if (fieldValue == null){
fieldValue = "0";
}else {
fieldValue = fieldValue.toString();
}
return fieldValue;
}));
stringRedisTemplate.opsForHash().putAll( "user:cache:"+ id,map);
return Result.ok(user);
这样问题就解决啦!!!
其实跟大家说一下我在这个问题上的经历:
这个问题是我去年刚接触到Hutool就遇到了,当时在为啥我都忽略空值,还是报空指针异常,我也知道问题在哪个地方出问题了,但是我不知道怎么解决,求助度娘也找到好的方法,给我折磨透了,当时我的解决方法是:
因为是自己练习的项目,就直接简单粗暴,在javaBean里将所有属性都给初始化一下,String初始化 “”,Long类型的初始化为 0L 这样他toString()就不会报空指针啦,当时算是解决了,就把这个问题给放下来了
那为什么我现在才发这篇文章呐,纯属是因为 在实习的过程中我又遇到这个问题了,因为这个是公司的项目,绝对不可以在实体类里对属性赋值的,对于这个问题我有印象,知道问题所在,也知道百度找不到好答案,就问我的导师,我导师就让我写了个demo,然后他debug给我看的,一点一点给我解释的, 然后我现在才知道为什么忽略空值了还会空指针, 也给我看了在Gitee上这个作者的回答 现在才彻底搞明白 算起来也算 过程坎坷吧,去年的问题今年解决 ,哈哈哈哈哈哈!!!
最后,如果帮助到你了,点个小心心吧,以后共同成长~~~~