Hutool工具包的BeanUtil的beanToMap方法------空指针的问题

x33g5p2x  于2022-08-17 转载在 其他  
字(2.7k)|赞(0)|评价(0)|浏览(1753)

Hutool工具包的BeanUtil的beanToMap方法------空指针的问题

前言:

​ 首先将一下为什么遇到了这个问题:

平时我们向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上看作者的回答:

原因:

  1. setFieldValueEditor优先级要高于ignoreNullValue导致前者首先被触发,因此出现空指针问题。你在setFieldValueEditor中也需要判空。
  2. 这么设计的原因主要是,如果原值确实是null,但是你想给一个默认值,在此前过滤掉就不合理了,而你的值编辑后转换为null,后置的判断就会过滤掉。

​ 原文链接在这里,大家可以参考一下:
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上这个作者的回答 现在才彻底搞明白 算起来也算 过程坎坷吧,去年的问题今年解决 ,哈哈哈哈哈哈!!!

最后,如果帮助到你了,点个小心心吧,以后共同成长~~~~

相关文章