Mybatis自定义TypeHandler

Mybatis是一个优秀的持久层框架,它提供了丰富的功能来简化数据库操作。在Mybatis中,TypeHandler是用于处理Java对象与数据库字段之间的类型转换的组件。自定义TypeHandler可以帮助我们处理一些特殊的数据类型或者自定义的数据类型。

自定义TypeHandler需要实现org.apache.ibatis.type.TypeHandler接口,并重写其中的方法。主要包括以下几个方法:

  1. setParameter:用于将Java对象转换为JDBC参数进行设置。
  2. getResult:用于将数据库字段的值转换为Java对象进行返回。
  3. getResult(CallableStatement cs, int columnIndex):用于将数据库字段的值转换为Java对象进行返回,支持存储过程。
  4. getResult(ResultSet rs, String columnName):用于将数据库字段的值转换为Java对象进行返回,通过字段名获取值。
  5. getResult(ResultSet rs, int columnIndex):用于将数据库字段的值转换为Java对象进行返回,通过字段索引获取值。

下面是一个自定义TypeHandler的示例代码:

java 复制代码
public class MyCustomTypeHandler implements TypeHandler<MyCustomType> {

    @Override
    public void setParameter(PreparedStatement ps, int i, MyCustomType parameter, JdbcType jdbcType) throws SQLException {
        // 将Java对象转换为JDBC参数进行设置
        ps.setString(i, parameter.toString());
    }

    @Override
    public MyCustomType getResult(ResultSet rs, String columnName) throws SQLException {
        // 将数据库字段的值转换为Java对象进行返回
        String value = rs.getString(columnName);
        return new MyCustomType(value);
    }

    @Override
    public MyCustomType getResult(ResultSet rs, int columnIndex) throws SQLException {
        // 将数据库字段的值转换为Java对象进行返回
        String value = rs.getString(columnIndex);
        return new MyCustomType(value);
    }

    @Override
    public MyCustomType getResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 将数据库字段的值转换为Java对象进行返回,支持存储过程
        String value = cs.getString(columnIndex);
        return new MyCustomType(value);
    }
}

在Mybatis的配置文件中,我们需要注册自定义的TypeHandler。可以通过在标签中添加子标签来进行配置,示例如下:

xml 复制代码
<typeHandlers>
    <typeHandler handler="com.example.MyCustomTypeHandler"/>
</typeHandlers>

这样,Mybatis就会在需要处理MyCustomType类型的字段时,使用我们自定义的TypeHandler进行类型转换。

如果项目是使用SpringBoot开发,也可以直接在类配置器的获取sqlSessionFactory实例的方法中进行注入。

其实Mybatis默认提供了一些基本类型的类型转换器,我们可以参照这些类型转换器去自定义。

在这个包目录下:org.apache.ibatis.type

我们随便看一个实现类:BigDecimalTypeHandler

java 复制代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.apache.ibatis.type;

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

public class BigDecimalTypeHandler extends BaseTypeHandler<BigDecimal> {
    public BigDecimalTypeHandler() {
    }

    public void setNonNullParameter(PreparedStatement ps, int i, BigDecimal parameter, JdbcType jdbcType) throws SQLException {
        ps.setBigDecimal(i, parameter);
    }

    public BigDecimal getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getBigDecimal(columnName);
    }

    public BigDecimal getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getBigDecimal(columnIndex);
    }

    public BigDecimal getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getBigDecimal(columnIndex);
    }
}

很简单,就是继承了BaseTypeHandler接口,然后实现其中的抽象方法就可以了。

我们可以自己实现这个BigDecimal的类型转换器,比如我这里自定义了一个BigDecimal类型转换器,默认将查询的结果小数点后面的0去掉。

java 复制代码
package com.au.sa.storeRebate.common.handler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.stereotype.Component;

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

/**
 * @author xiaohuihui
 * @creteTime 2024-05-01 10:53
 * @description
 */
@Component
public class BigDecimalTypeHandler extends BaseTypeHandler<BigDecimal> {

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

    @Override
    public BigDecimal getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getBigDecimal(columnName).stripTrailingZeros();
    }

    @Override
    public BigDecimal getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getBigDecimal(columnIndex).stripTrailingZeros();
    }

    @Override
    public BigDecimal getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getBigDecimal(columnIndex).stripTrailingZeros();
    }
}

然后在Mybatis数据源的配置类中,注入Handler的包扫描路径就可以了。

java 复制代码
@Primary
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("master") DataSource dataSource, @Qualifier("mybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        LOGGER.info("数据库连接池信息:{}", ((HikariDataSource)dataSource).getIdleTimeout());
        GlobalConfig globalConfig=new GlobalConfig();
        globalConfig.setMetaObjectHandler(metaObjectHandler);
        sqlSessionFactory.setGlobalConfig(globalConfig);
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setMapUnderscoreToCamelCase(true);
        if (Objects.equals(isShowSql, true)) {
            configuration.setLogImpl(StdOutImpl.class);
        }
        configuration.setCacheEnabled(false);
        configuration.addInterceptor(mybatisPlusInterceptor);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        sqlSessionFactory.setTypeHandlersPackage("com.au.sa.storeRebate.common.handler");
        return sqlSessionFactory.getObject();
    }

就是这一行代码:

java 复制代码
sqlSessionFactory.setTypeHandlersPackage("com.au.sa.storeRebate.common.handler");

也可以采用这种形式:

java 复制代码
    @Resource
    private BigDecimalTypeHandler bigDecimalTypeHandler;


    sqlSessionFactory.setTypeHandlers(bigDecimalTypeHandler);

实现的效果:

返回的结果自动将小数点后面的0去除了。

相关推荐
你不是我我7 小时前
【Java 开发日记】HTTP3 性能更好,为什么内网微服务依然多用 HTTP2?HTTP2 内网优势是什么?
java·开发语言·微服务
雪碧聊技术7 小时前
大模型爆火!Java后端如何抓住Agent全栈开发的风口
java·大模型·agent·全栈开发
逻辑驱动的ken8 小时前
Java高频面试场景题25
java·开发语言·深度学习·面试·职场和发展
AI人工智能+电脑小能手9 小时前
【大白话说Java面试题】【Java基础篇】第32题:Java的异常处理机制是什么
java·开发语言·后端·面试
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ11 小时前
通过java后端代码来实现给word内容补充格式文本内容控件,以及 设置控件的标记和标题
java·c#·word
無限進步D11 小时前
Java 面向对象高级 接口
java·开发语言
逸Y 仙X12 小时前
文章二十七:ElasticSearch ES查询模板(Search Template)高效复用实战
java·大数据·数据库·elasticsearch·搜索引擎·全文检索
二哈赛车手12 小时前
新人笔记---Spring AI的Advisor以及其底层机制讲解(涉及源码),包含一些遇见的Spring AI的Advisor缺陷问题的解决方案
java·人工智能·spring boot·笔记·spring
AC赳赳老秦12 小时前
接口测试自动化:用 OpenClaw 对接 Postman,实现批量回归测试、测试报告自动生成与推送
java·人工智能·python·算法·elasticsearch·deepseek·openclaw