Loading

MyBatis 查询结果自动封装为map,出现null而没有字段名

date: 2020-11-03 17:14:00
updated: 2020-11-03 17:40:00

MyBatis 查询结果自动封装为map,出现null而没有字段名

  1. 问题
select a, b, c from table
>> 
a   b   c

1      
// 查询结果中,第一条数据这三个字段都是null,没有值,第二条数据只有a字段有值,在自动封装为hashmap返回时的结果如下:
[
    null,
    {
        "a": 1
    }
]
  1. 原因:

org.apache.ibatis.executor.resultset.DefaultResultSetHandler 类下面找到 getRowValue 方法

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
    final MetaObject metaObject = configuration.newMetaObject(rowValue);
    boolean foundValues = this.useConstructorMappings;
    if (shouldApplyAutomaticMappings(resultMap, false)) {
    foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
    }
    foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
    foundValues = lazyLoader.size() > 0 || foundValues;
    rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
return rowValue;
}

在对 rowValue 赋值的时候,会去判断语句查询是否有值 或者 configuration.isReturnInstanceForEmptyRow() 这个配置项是否为true,如果前面都是false的话,就置为null,也就是最后返回结果里null的原因

参数 含义 有效值 默认值
callSettersOnNulls 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 true ` ` false
returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) true ` ` false
  1. 解决:

在 mybatis-config.xml 文件里添加两个参数

<configuration>
    <settings>
<!--        指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法-->
        <setting name="callSettersOnNulls" value="true"/>
<!--        当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)-->
        <setting name="returnInstanceForEmptyRow" value="true"/>
    </settings>
</configuration>

在 application.properties 里去指定 mybatis-config.xml 的路径

mybatis.config-location: mybatis-config.xml

或者在注册sqlFactory的时候,去指定configLocation

bean.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-config.xml"));
posted @ 2020-11-12 17:39  猫熊小才天  阅读(1168)  评论(0编辑  收藏  举报