BaseTypeHandler用法-笔记

发布于:2025-06-01 ⋅ 阅读:(26) ⋅ 点赞:(0)

1.BaseTypeHandler简介

org.apache.ibatis.type.BaseTypeHandler 是 MyBatis 提供的一个抽象类,通过继承该类并实现关键方法,可用于实现 Java 类型 与 JDBC 类型 之间的双向转换。当数据库字段类型与 Java 对象属性类型不一致时(如:枚举类型、自定义对象、JSON 字段等),可以通过自定义 BaseTypeHandler 实现灵活的数据类型映射。


1.1 核心方法

BaseTypeHandler<T> 是泛型类,其中 T 表示 Java 类型。需要实现以下 4 个核心方法:

方法 作用
void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) 将 Java 类型转换为 JDBC 类型,设置到 SQL 语句中
T getNullableResult(ResultSet rs, String columnName) 从 ResultSet 中通过列名获取 Java 类型值
T getNullableResult(ResultSet rs, int columnIndex) 从 ResultSet 中通过列索引获取 Java 类型值
T getNullableResult(CallableStatement cs, int columnIndex) 从存储过程结果中通过列索引获取 Java 类型值

1.2 典型使用场景

  1. 枚举类型映射:将数据库中的字符串或整数映射为 Java 枚举。
  2. 复杂对象映射:将 JSON 字符串转换为 Java 对象(如 List<T> 或自定义类)。
  3. 特殊类型转换:将数据库中的 DATE/TIMESTAMP 映射为 LocalDateTime 等。

2. 使用示例

2.1 枚举类型转换

将自定义的枚举类型与数据库里的String类型做自动转换。

step1.定义枚举类

public enum Status {
    ACTIVE("active"),
    INACTIVE("inactive");

    private final String code;

    Status(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    public static Status fromCode(String code) {
        for (Status status : values()) {
            if (status.code.equals(code)) {
                return status;
            }
        }
        throw new IllegalArgumentException("Invalid code: " + code);
    }
}

step2.自定义 TypeHandler,用于将枚举 Status 类和数据库中的String类做转换

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

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

public class StatusTypeHandler extends BaseTypeHandler<Status> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter.getCode());
    }

    @Override
    public Status getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String code = rs.getString(columnName);
        return code == null ? null : Status.fromCode(code);
    }

    @Override
    public Status getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String code = rs.getString(columnIndex);
        return code == null ? null : Status.fromCode(code);
    }

    @Override
    public Status getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String code = cs.getString(columnIndex);
        return code == null ? null : Status.fromCode(code);
    }
}

step3. 在XML映射文件中使用

  • status在数据库users表里是一个String类型字符串;在 User类里是一个 Status 枚举类型对象
  • 经过StatusTypeHandler处理后,可以将数据库的String类型映射为User里的Status枚举类型
<!-- UserMapper.xml -->
<resultMap id="userResultMap" type="User">
    <result column="status" property="status" typeHandler="com.example.StatusTypeHandler"/>
</resultMap>

<select id="selectUser" resultMap="userResultMap">
    SELECT * FROM users WHERE id = #{id}
</select>

2.2 JSON类型转换

将JSONObject类型与数据库里的String类型做转换:

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

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

import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSONObject;


public class JSONObjectTypeHandler extends BaseTypeHandler<JSONObject> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JSONObject parameter, JdbcType jdbcType)
        throws SQLException {
        ps.setString(i, parameter == null ? "{}" : parameter.toJSONString());
    }

    @Override
    public JSONObject getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return StringUtils.isBlank(json) ? new JSONObject() : JSONObject.parseObject(json);
    }

    @Override
    public JSONObject getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return StringUtils.isBlank(json) ? new JSONObject() : JSONObject.parseObject(json);
    }

    @Override
    public JSONObject getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return StringUtils.isBlank(json) ? new JSONObject() : JSONObject.parseObject(json);
    }
}

2.3 注意事项

  1. 空值处理:在 getNullableResult 中需判断 null,避免 NPE。
  2. 线程安全:避免在 TypeHandler 中使用可变成员变量。
  3. 性能优化:避免在转换过程中频繁创建对象(如 JSON 序列化器)。

网站公告

今日签到

点亮在社区的每一天
去签到