场景解决之mybatis当中resultType= map时,因某个字段为null导致返回的map的key不存在怎么处理

1、场景:通过查询数据表将返回结果封装到map当中返回,因某个字段为null,导致map当中key丢失

java 复制代码
<select id="queryMyBonus" parameterType="com.cn.entity.student" resultType= "map">
        SELECT
        b.projectName as "projectName",
        b.money as "money",
        b.yearMonthDay as "yearMonthDay",
        b.description as "description"
        FROM
        Student b
        <where>
            <if test='userId != null and userId != ""'>
                AND b.USERID = #{userId,jdbcType=VARCHAR}
            </if>
        </where>
        order by b.YEARMONTHDAY desc, b.totalFlag desc, b.BONUSID asc
    </select>

注意上面的resultType= "map",此时当查询结果为

返回的map结果为,丢失了description

2、解决方案

  1. 修改查询SQL:在查询SQL中使用数据库函数(如 IFNULL 或 COALESCE )来为可能为 null 的字段提供一个默认值。
  2. 使用实体类代替Map:如果可能,修改返回类型为一个实体类而不是 map ,这样即使字段值为 null ,也会在实体类中正确地表示出来。
  3. 配置MyBatis:在MyBatis的配置文件中设置 callSettersOnNulls 属性为 true 。这会使得MyBatis在处理结果集时,即使字段值为 null 也会调用映射对象的setter方法(对于 map 来说就是 put 方法),从而在 map 中包含这个键。在 mybatis-config.xml 中添加如下配置
java 复制代码
<configuration>
  <settings>
  <!--  这个修改是全局的 -->
    <setting name="callSettersOnNulls" value="true"/>
  </settings>
</configuration>

如果是Spring Boot项目,可以在 application.properties 或 application.yml 中添加:

properties:

java 复制代码
mybatis.configuration.call-setters-on-nulls=true

yaml:

java 复制代码
mybatis:
  configuration:
    call-setters-on-nulls: true
  1. 自定义TypeHandler:创建一个实现 TypeHandler 接口的类,用于处理 null 值的情况。
java 复制代码
/**
 * 自定义类型处理器,用于将数据库中的null值转换为空字符串
 * 这在避免空指针异常和统一数据处理逻辑方面非常有用
 */
package com.cn.config;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class EmptyStringIfNull implements TypeHandler<String> {
    /**
     * 设置参数值到PreparedStatement中
     * 本方法暂未实现,因为在这种情况下不需要特殊处理
     *
     * @param ps          预编译的SQL语句对象
     * @param i           参数索引
     * @param parameter   参数值
     * @param jdbcType    JDBC类型
     * @throws SQLException 如果操作数据库时发生错误
     */
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // 无需特殊处理,保留默认行为
    }

    /**
     * 从ResultSet中根据列名获取结果,并将null值转换为空字符串
     * 这是处理null值的关键方法
     *
     * @param rs          结果集对象
     * @param columnName  列名
     * @return            字符串结果,如果数据库中的值为null,则返回空字符串
     * @throws SQLException 如果操作数据库时发生错误
     */
    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        // 获取字符串值,如果为null,则返回空字符串
        return (rs.getString(columnName) == null) ? "" : rs.getString(columnName);
    }

    /**
     * 从ResultSet中根据列索引获取结果
     * 本方法未实现,因为当前逻辑不需要使用列索引获取结果
     *
     * @param rs          结果集对象
     * @param columnIndex 列索引
     * @return            未使用,始终返回null
     * @throws SQLException 如果操作数据库时发生错误
     */
    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        // 无需处理,返回null
        return null;
    }

    /**
     * 从CallableStatement中根据列索引获取结果
     * 本方法未实现,因为当前逻辑不需要通过CallableStatement获取结果
     *
     * @param cs          可调用语句对象
     * @param columnIndex 列索引
     * @return            未使用,始终返回null
     * @throws SQLException 如果操作数据库时发生错误
     */
    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 无需处理,返回null
        return null;
    }
}

使用方式:

将select标签的resulttype=map 改成resultMap映射

java 复制代码
 <!-- 查询信息 -->
    <resultMap id="BonusResultMap" type="map">
        <result property="projectName" column="projectName"/>
        <result property="money" column="money"/>
        <result property="yearMonthDay" column="yearMonthDay"/>
        <result property="description" column="description" typeHandler="com.cn.config.EmptyStringIfNull"/>
    </resultMap>

上述配置 typeHandler="com.cn.config.EmptyStringIfNull"

可以单个指定使用较为方便

结果验证:

相关推荐
꧁惜若༒奔已꧂2 小时前
spring使用xml文件整合事务+druid+mybatis
xml·spring·mybatis
小桥流水人家jjh5 小时前
Mybatis执行自定义SQL并使用PageHelper进行分页
java·数据库·spring boot·sql·mybatis
黑马师兄6 小时前
Mybatis
java·mybatis
ZWZhangYu1 天前
【MyBatis源码】深入分析TypeHandler原理和源码
数据库·oracle·mybatis
小鸡脚来咯2 天前
springboot 整合mybatis
java·spring boot·mybatis
种树人202408192 天前
MyBatis xml 文件中 SQL 语句的小于号未转义导致报错
mybatis
码农派大星。2 天前
MyBatis操作--进阶
mybatis
爱读源码的大都督2 天前
MyBatis中的LanguageDriver的作用是什么
java·spring boot·mybatis
鹿屿二向箔2 天前
基于SSM(Spring + Spring MVC + MyBatis)框架的快递管理系统
spring·mvc·mybatis