mybatis TypeHandler类型处理器介绍

MyBatis 的 `TypeHandler` 是一个非常重要的接口,它负责在 PreparedStatement 设置参数和 ResultSet 读取结果时,进行 Java 类型和 JDBC 类型之间的转换。以下是 `TypeHandler` 接口中定义的一些关键方法:

1. `setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)`: 将 Java 类型转换为 JDBC 类型,并设置到 PreparedStatement 中。
2. `getResult(ResultSet rs, String columnName)`: 从 ResultSet 中按照列名读取数据,并转换为 Java 类型。
3. `getResult(ResultSet rs, int columnIndex)`: 从 ResultSet 中按照列索引读取数据,并转换为 Java 类型。
4. `getResult(CallableStatement cs, int columnIndex)`: 从 CallableStatement 中按照列索引读取数据,并转换为 Java 类型。

此外,`BaseTypeHandler` 是 `TypeHandler` 接口的一个抽象实现类,它提供了一些基本的实现,使得创建自定义类型处理器时只需要覆盖必要的方法。通常需要实现或覆盖以下方法:

1. `setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)`: 设置非空的参数值。
2. `getNullableResult(ResultSet rs, String columnName)`: 根据列名获取可能为null的结果。
3. `getNullableResult(ResultSet rs, int columnIndex)`: 根据列索引获取可能为null的结果。
4. `getNullableResult(CallableStatement cs, int columnIndex)`: 从存储过程的结果集中根据列索引获取可能为null的结果。

自定义 `TypeHandler` 时,可以通过在类上使用 `@MappedTypes` 和 `@MappedJdbcTypes` 注解来指定处理的 Java 类型和 JDBC 类型,或者在 MyBatis 配置文件中注册自定义的 `TypeHandler`。

MyBatis 还提供了许多内置的 `TypeHandler`,例如 `BooleanTypeHandler`、`IntegerTypeHandler`、`StringTypeHandler`、`DateTypeHandler` 等,它们能够处理大部分常见的数据类型转换。如果需要处理特殊的数据类型或转换逻辑,可以通过实现 `TypeHandler` 接口或继承 `BaseTypeHandler` 类来创建自定义的 `TypeHandler` 实现。

在实际开发中,自定义 `TypeHandler` 可以用于处理枚举类型、复杂数据类型(如 JSON 字符串与 Java 对象之间的转换),或者实现特殊的类型转换逻辑,以满足特定的业务需求。自定义 `TypeHandler` 的注册可以通过配置文件、注解或编程方式进行。


常用场景

BigInt类型存储时间戳,自动处理成Date格式

第一步自定义一个TypeHandler

package com.handler;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.*;
import java.util.Date;

@MappedTypes(java.util.Date.class)
@MappedJdbcTypes(JdbcType.BIGINT)
public class BigIntToDateTypeHandler implements TypeHandler<Date> {

    @Override
    public void setParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
        System.out.println("--------------------------------------------------");
        System.out.println(jdbcType);
        System.out.println("--------------------------------------------------");
        if (parameter != null) {
            ps.setLong(i, parameter.getTime());
        } else {
            ps.setNull(i, Types.BIGINT);
        }
    }

    @Override
    public Date getResult(ResultSet rs, String columnName) throws SQLException {
        long millis = rs.getLong(columnName);
        if (rs.wasNull()) {
            return null;
        }
        return new Date(millis);
    }

    @Override
    public Date getResult(ResultSet rs, int columnIndex) throws SQLException {
        long millis = rs.getLong(columnIndex);
        if (rs.wasNull()) {
            return null;
        }
        return new Date(millis);
    }

    @Override
    public Date getResult(CallableStatement cs, int columnIndex) throws SQLException {
        long millis = cs.getLong(columnIndex);
        if (cs.wasNull()) {
            return null;
        }
        return new Date(millis);
    }
}

把自定义的处理器注册到mybatis当中

@Configuration
public class MyBatisConfig {

    @Bean
    public ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return configuration -> {
            configuration.getTypeHandlerRegistry().register(BigIntToDateTypeHandler.class);
        };
    }
}

然后实体类属性由


  private Long lastLoginTime;

改成

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")// 用于 JSON 序列化和反序列化
  @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 用于 Spring MVC 数据绑定
  private Date lastLoginTime;

这样从数据库中取出来的毫秒级别的时间戳就可以转成Date类型


如果要把Date类型数据 存到数据库的bigint类型

在映射文件中,指定一下jdbcType类型

#{lastLogin,jdbcType=BIGINT}

posted @ 2024-09-05 12:35  在线电影制作人  阅读(5)  评论(0)    收藏  举报  来源