开发者

MyBatis类型处理器TypeHandler的作用及说明

目录
  • 为什么需要 TypeHandler?
  • TypeHandler 的作用
  • TypeHandler 的接口定义
  • MyBATis 内置的 TypeHandler
  • 自定义 TypeHandler
  • 自定义 TypeHandler 的步骤
  • 总结

TypeHandler 是 MyBatis 中用于处理 Java 类型与 JDBC 类型之间转换的接口。它在 MyBatis 的参数绑定和结果映射过程中起着至关重要的作用。

为什么需要 TypeHandler?

Java 和 数据库(JDBC)使用不同的类型系统。例如:

  • Java 中有 StringIntegerDateBooleanenum 等类型。
  • JDBC 中有 VARCHARINTEGERDATEBOOLEANTIMESTAMPBLOB 等类型。

当 MyBatis 执行 SQL 语句时,需要将 Java 对象中的数据设置到 JDBC 的 PreparedStatement 中(参数绑定),以及将 JDBC 的 ResultSet 中的数据转换为 Java 对象(结果映射)。TypeHandler 就负责处理这两种情况下的类型转换。

TypeHandler 的作用

参数绑定 (Java 类型 -> JDBC 类型):

  • 当 MyBatis 将 Java 对象中的数据设置到 PreparedStatement 的占位符(#{})时,TypeHandler 会将 Java 类型转换为对应的 JDBC 类型。
  • 例如,将 Java 的 String 类型转换为 JDBC 的 VARCHAR 类型,将 Java 的 Date 类型转换为 JDBC 的 TIMESTAMP 类型。

结果映射 (JDBC 类型 -> Java 类型):

  • 当 MyBatis 从 ResultSet 中读取数据并将其映射为 Java 对象时,TypeHandler 会将 JDBC 类型转换为对应的 Java 类型。
  • 例如,将 JDBC 的 VARCHAR 类型转换为 Java 的 String 类型,将 JDBC 的 INTEGER 类型转换为 Java 的 Integer 类型。

TypeHandler 的接口定义

public interface TypeHandler<T> {

  // 参数绑定:将 Java 类型转换为 JDBC 类型,并设置到 PreparedStatement 中
  void setParameter(PreparedStatement ps, int i, T parameter, J编程客栈dbcType jdbcType) throws SQLException;

  // 结果映射:从 ResultSet 中获取指定列的数据,并将其转换为 Java 类型
  T getResult(ResultSet rs, String columnName) throws SQLException;

  // 结果映射:从 ResultSet 中获取指定列索引的数据,并将其转换为 Java 类型
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
  
    // 结果映射:从 CallableStatement 中获取指定列索引的数据,将其转换为java类型
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
  • setParameter(): 将 Java http://www.devze.com类型的参数 parameter 设置到 PreparedStatement 的第 i 个占位符,并指定 JDBC 类型 jdbcTypejdbcType 可以为空,MyBatis 会尝试自动推断)。
  • getResult(): 有三个重载方法,分别根据列名、列索引从 ResultSet 中获取数据,或从CallableStatement获取数据,并将其转换为 Java 类型。

MyBatis 内置的 TypeHandler

MyBatis 内置了许多常用的 TypeHandler,用于处理常见的类型转换。例如:

  • StringTypeHandler: 处理 String 类型。
  • IntegerTypeHandler: 处理 Integer 类型。
  • LongTypeHandler: 处理 Long 类型。
  • DateTypeHandler: 处理 java.util.Date 类型。
  • BooleanTypeHandler: 处理 Boolean 类型。
  • EnumTypeHandler: 处理枚举类型(默认使用枚举的名称)。
  • EnumOrdinalTypeHandler: 处理枚举类型(使用枚举的序数)。
  • BlobTypeHandler: 处理二进制大对象 (BLOB)。
  • ClobTypeHandler: 处理字符大对象 (CLOB)。
  • SqlDateTypeHandler:处理java.sql.Date类型
  • SqlTimeTypeHandler:处理java.sql.Time类型
  • SqlTimestampTypeHandler:处理java.sql.Timestamp类型

自定义 TypeHandler

当 MyBatis 内置的 TypeHandler 不能满足需求时,我们可以自定义 TypeHandler。例如:

  • 处理特殊类型: 例如,将数据库中的 jsON 字符串转换为 Java 对象,或者将 Java 对象转换为 JSON 字符串存储到数据库中。
  • 自定义类型转换逻辑: 例如,对日期类型进行特殊的格式化,或者对枚举类型使用自定义的转换规则。

自定义 TypeHandler 的步骤

1.实现 TypeHandler 接口: 创建一个类,实现 TypeHandler 接口,并实现接口中的方法。

2.注册 TypeHandler: 有两种方式注册自定义的 TypeHandler

  • XML 配置:mybatis-config.xml 文件中,使用 <typeHandlers> 标签注册 TypeHandler
<typeHandlers>
  <typeHandler handler="com.example.MyTypeHandler" javaType="com.example.MyType" jdbcType="VARCHAR"/>
</typeHandlers>
  • 或者使用包扫描:
 <typeHandlers>
     <package name="com.example.typehandler"/>
 </typeHandlers>
  • 注解配置: 在自定义的 TypeHandler 类上使用 @MappedTypes@MappedJdbcTypes 注解。
@MappedTypes(MyType.class) // 指定 Java 类型
@MappedJdbcTypes(JdbcType.VARCHAR) // 指定 JDBC 类型
public class MyTypeHandler implements TypeHandler<MyType> {
    // ... 实现 TypeHandler 接口的方法 ...
}

3.指定jdbcType(可选): 如果MyBatis无法推断,则必须通过jdbcType属性为null值指定数据库列的类型

  • 示例:
  • 自定义一个将数据库中的 VARCHAR 类型转换为 Java 中的枚举类型的 TypeHandler:
// 假设有一个枚举类型
public enum Status {
    ACTIVE, INACTIVE, PENDING
}

// 自定义 TypeHandler
@MappedTypes(Status.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class StatusTypeHandler implements TypeHandler<Status> {

    @Overjavascriptride
    public void setParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            ps.setString(i, null);
        } else {
            ps.setString(i, parameter.name()); // 将枚举的名称存储到数据库
        }
    }

    @Override
    public Status getResult(ResultSet rs, String columnName) throws SQLException {
        String value = rs.getString(columnName);
        return getStatus(value);
    }

    @Override
    public Status getResult(ResultSet rs, int columnIndex) throws SQLException {
        String value = rs.getString(columnIndex);
         return getStatus(value);
    }

    @Override
    public Status getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value = cs.getString(columnIndex);
        return getStatus(value);
    }
    
    private Status getStatus(String value){
         if (value == null) {
            return null;
        }
        try {
            return Status.valueOf(value); // 根据名称从数据库中获取枚举值
        } catch (IllegalArgumentException e) {
            return null; // 或者抛出异常
        }
    }
}

// 在 mybatis-config.xml 中注册 TypeHandler
<typeHandlers>
  <typeHandler handler="com.example.StatusTypeHandler"/>
</typeHandlers>

// 或者在 Mapper XML 文件中使用
<resultMap id="userResultMap" type="User">
    <result property="status" column="status" javaType="com.example.Status" jdbcType="VARCHAR" typeHa编程客栈ndler="com.example.StatusTypeHandler"/>
</resultMap>

总结

TypeHandler 是 MyBatis 中用于处理 Java 类型与 JDBC 类型之间转换的关键组件。

MyBatis 内置了许多常用的 TypeHandler,在大多数情况下,我们可以直接使用内置的 TypeHCSbvzgandler

当需要处理特殊类型或自定义类型转换逻辑时,我们可以自定义 TypeHandler,并通过 XML 配置或注解的方式注册自定义的 TypeHandler

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜