今天跟大家讨论下mybatis查询Map接收值为null不存key的问题
问题出现的前提条件:将数据从DB中查询出来时将查出来的字段映射为Map,而不是封装成Bean.
我们看下mybatis查询使用map接收时遇到的问题:
xml文件:
SELECT
a.apply_id AS "applyId",
a.ali_pid AS "aliPid",
a.ali_account AS "aliAccount",
a.agreement_resource_ids AS "agreementResourceIds",
a.status AS "status",
a.error_field AS "errorField",
ac.company_name AS "companyName",
u.name AS "userName",
DATE_FORMAT(a.create_date,'%Y-%m-%d') AS "createDate",
sa1.name AS "provinceName",
sa2.name AS "cityName",
sa3.name AS "regionName",
ac.address AS "address",
acbac.status AS "aliStatus",
acbl.reason_desc AS "reasonDesc",
aac.memo AS "memo"
返回结果:
applyId=174, address=测试, cityName=北京市, aliPid=2088123123123213, aliAccount=123123123123, companyName=企业20181212, regionName=东城区, provinceName=北京, userName=张三, aliStatus=3, status=2, createDate=2018-12-28
根据返回结果看到,并没有memo字段,原因是该字段在DB中的值为null,所以说map接收数据库中为null的值不会存在对应的键值。
出现这种情况的原因:
maibatis在默认情况下,对Map的解析生成如果value为null的话,那么key不会被加入到map中,所以map接收结果时就没有value为null的键值。
解决方法:在mybatis配置文件中设置callSettersOnNulls设置为true,该属性默认为false。
callSetterOnNulls:指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。
<!-- 全局参数 -->
<settings>
<!-- 设置当结果集中为null,调用setter(map 为put)方法 -->
<setting name="callSettersOnNull" value="true"/>
</settings>
加上该配置的返回结果:
memo=null, address=测试, aliPid=2088123123123213, companyName=测试企业20181212, regionName=东城区, userName=张三, applyId=174, errorField=null, cityName=北京市, aliAccount=123123123123, provinceName=北京, agreementResourceIds=null, aliStatus=3, reasonDesc=null, status=2, createDate=2018-12-28
在应用层查询的map已经有这个键值了,解决了结果集为null但是没用存键值的问题。
在解决该问题过程中,看到网上有说如果只查询一个字段,并且结果为null用map接收时,结果为空map。
就此我进行了测试:
xml文件:
SELECT a.memo AS "memo" from a
结果:
{memo=null}
经此实验这种说法是不正确的,接收到一个所有key值都为null 的map 而不是一个为null的map;
但是我带到页面上的结果还是没有memo这个字段,(一直以为是这个配置没有起作用,只顾着看前端接收到的返回值,没有关注后端的结果。自己要蠢死了)
最后找到了问题,因为我应用层使用了Gson序列化
return GsonUtil.getGson().toJson(map);
Gson默认当属性的值设为空时不会被序列化,如果强制序列化null值,我们可以使用GsonBuilder来序列化提供null值;
new GsonBuilder().serializeNulls().create().toJson(result);可以将null值也序列化。
前端页面接收返回结果:
如果跟大家理解有出入,欢迎提出一起讨论。。。。。