admin管理员组

文章数量:1538180

一 概述

MyBatis类型转换器是用于在Java类型和JDBC类型之间进行转换的工具。它可以将Java对象转换为JDBC可用的对象,也可以将JDBC对象转换为Java对象。Java类型是指在Java编程语言中定义的数据类型,如String、Integer、Date等。JDBC类型是指在关系型数据库中定义的数据类型,如VARCHAR、INTEGER、DATE等。
在MyBatis中,类型转换器是通过实现TypeHandler接口来完成的。它有两个主要方法:setNonNullParametergetNullableResultsetNonNullParameter方法用于将Java对象转换为JDBC可用的对象,并将其设置为PreparedStatement对象的参数。getNullableResult方法用于从ResultSet对象中获取JDBC对象并将其转换为Java对象。 MyBatis默认提供了许多类型转换器,如StringTypeHandler、IntegerTypeHandler、DateTypeHandler等。如果需要自定义类型转换器,可以通过实现TypeHandler接口并在MyBatis配置文件中进行配置来实现。
为什么要用它,举一些可能出现的应用场景:

  1. 在数据库中采用varchar、text等字符串类型存储一个整形id集合,id间采用“,”分隔符分割,但在Java(MyBatis)实体中我们希望使用List ids来映射数据库中的字段;
  2. 做GIS开发的,PostGIS库中的geometry几何字段,但在Java(MyBatis)实体中我们希望使用GeoTools的Java几何类型来映射PostGIS数据库中的几何字段,此类实现参考我的另一篇文章 《使用MyBatis类型转换器将PostGIS中的几何字段转为PostGIS/GeoTools的几何Java对象》;

二 MyBatis预设的一些TypeHandler

TypeHandlerJdbcTypeJavaType
ArrayTypeHandlerARRAYArray
BigDecimalTypeHandlerNUMERICBigDecimal, BigInteger
BigIntegerTypeHandlerNUMERICBigInteger
BlobTypeHandlerBLOBBlob, byte[]
BooleanTypeHandlerBITBoolean, boolean
ByteTypeHandlerTINYINTByte, byte
ByteObjectArrayTypeHandlerARRAYByte[]
ByteObjectTypeHandlerTINYINTByte
CharacterTypeHandlerCHARCharacter, char
ClobTypeHandlerCLOBClob, String
DateOnlyTypeHandlerDATEDate
DateTypeHandlerTIMESTAMPDate, java.sql.Date
DoubleTypeHandlerDOUBLEDouble, double
EnumOrdinalTypeHandlerINTEGEREnum
EnumTypeHandlerVARCHAREnum
FloatTypeHandlerREALFloat, float
IntegerTypeHandlerINTEGERInteger, int
JdbcTypeHandlerOTHERObject
LocalDateTypeHandlerDATEjava.time.LocalDate
LocalDateTimeTypeHandlerTIMESTAMPjava.time.LocalDateTime
LongTypeHandlerBIGINTLong, long
ShortTypeHandlerSMALLINTShort, short
SqlTimeTypeHandlerTIMEjava.sql.Time
StringTypeHandlerVARCHARString
TimeOnlyTypeHandlerTIMEjava.sql.Time
TimestampTypeHandlerTIMESTAMPTimestamp

三 使用步骤

  1. 确认数据库中字段存储的JDBC类型和你希望实体中使用的Java类型;
  2. 自定义类型转换器类,实现TypeHandler接口,在获取值、插入值的方法中进行类型转换的代码实现;
  3. 字段类型转换配置,MyBatis和MyBatisPlus的配置有所不同,后者做出的更进一步的简化(基于注解);

1 字段类型转换配置 MyBatisPlus(推荐)

MyBatisPlus对类型转换器的配置就变得更加便捷直观,首先在SpringBoot项目配置文件中MyBatisPlus节点中配置typeHandler的包目录,然后在对应实体的@TableField注解中指定类型转换时使用的自定义类型转换器的类即可。

/**
* 班级包含的学生id列表
*/
@TableField(value = "student_ids", typeHandler = IntegerListTypeHandler.class)
private List<Integer> studentIds;
# mybatis-plus配置
mybatis-plus:
	# 类型转换器,指定到包
	type-handlers-package: com.xxx.entity.typeHandler

2 字段类型转换配置 MyBatis

(1)方式1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oxKMle2b-1684395901532)(https://cdn.nlark/yuque/0/2023/png/2968237/1684395089390-ad9464c5-75d7-4575-b99c-f9cb45c85ee7.png#averageHue=%2382754d&clientId=u24cbbbc3-cba1-4&from=paste&height=174&id=uec303ada&originHeight=174&originWidth=1050&originalType=binary&ratio=1&rotation=0&showTitle=false&size=26556&status=done&style=none&taskId=u25464c40-9559-44b8-a642-8b9f624e676&title=&width=1050)]
在对应实体的mapper.xml文件的resultMap节点下,对要进行转换处理的result节点中指定jdbcType、javaType和typeHandler即可。

  • jdbcType:关系型数据库中定义的数据类型
  • javaType:要转换的Java类型
  • typeHandler:自定义的类型转换器

(2)方式2

在自定义类型转换器上添加映射类型与映射Jdbc类型注解

@MappedTypes({List.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class IntegerListTypeHandler extends BaseTypeHandler<List<Integer>> {
    ...
}

在mybatis配置文件中添加如下配置:

<typeHandlers>
  <typeHandler handler="com.test.model.entity.IntegerListTypeHandler"/>
</typeHandlers>

四 自定义类型转换器示例

在数据库中采用varchar、text等字符串类型存储一个整形id集合,id间采用“,”分隔符分割,但在Java(MyBatis)实体中我们希望使用List ids来映射数据库中的字段。

public class IntegerListTypeHandler extends BaseTypeHandler<List<Integer>> {
    public static final String IdSplitter = ",";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<Integer> parameter, JdbcType jdbcType) throws SQLException {
        // 将List<Integer>类型的属性转换成数据库中的字符串
        StringBuilder sb = new StringBuilder();
        for (int num : parameter) {
            sb.append(num).append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        ps.setString(i, sb.toString());
    }

    @Override
    public List<Integer> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 将数据库中的字符串转换成List<Integer>类型的属性
        String str = rs.getString(columnName);
        return integerStringToIntegerList(str, IdSplitter);
    }

    @Override
    public List<Integer> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String str = rs.getString(columnIndex);
        return integerStringToIntegerList(str, IdSplitter);

    }

    @Override
    public List<Integer> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String str = cs.getString(columnIndex);
        return integerStringToIntegerList(str, IdSplitter);

    }

    /**
     * 将由指定分隔符形成的整型数列表字符串分割,返回整形List
     * <p>
     * integerListString:”1,2,3,4,5,6“
     * regex:","
     * result:new List<Integer>(){1,2,3,4,5,6}
     *
     * @param integerListString
     * @param regex
     * @return
     */
    private static List<Integer> integerStringToIntegerList(String integerListString, String regex) {
        if (integerListString != null && !integerListString.isEmpty()) {
            String[] nums = integerListString.split(regex);
            List<Integer> list = new ArrayList<>();
            for (String num : nums) {
                list.add(Integer.valueOf(num));
            }
            return list;
        }
        return new ArrayList<>();
    }
}

本文标签: 转换器类型MyBatis