news 2026/7/7 21:31:57

MyBatis/MyBatis-Plus类型转换器深度解析:从基础原理到自定义实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MyBatis/MyBatis-Plus类型转换器深度解析:从基础原理到自定义实践

目录

  • 前言
  • 基本概念
  • 一、TypeHandler
    • TypeHandler作用
    • 内置 TypeHandler 的自动映射
  • 二、jdbcType 的必要性:处理 NULL 值的核心
  • 三、自定义 TypeHandler

前言

这篇博客主要讲一下mybatis/mybatisplus框架的类型转换器的相关知识和用法,最近项目有一个技术场景,需要将 java String 字符串类型和数据库bigint字段类型互相自动转换,借此机会总结一下相关知识点。

基本概念

  1. MyBatis-Plus 底层依托 MyBatis 实现,而 MyBatis 最终是通过 JDBC 的 PreparedStatement 操作数据库。为防范 SQL 注入风险,PreparedStatement 会先将包含参数占位符的 SQL 语句发送至数据库完成编译和优化;随后,它会调用内部的类型转换器,把传入的 Java 参数转换成数据库对应的类型并传递给数据库,生成最终可执行的完整 SQL。数据库执行 SQL 后将结果返回给 Java 客户端,框架内部再通过反射机制,借助类型转换器把返回的字段数据映射为 Java 对象的属性。
  2. 关于类型转换器在上述过程的作用,可以借助这个流程图理解。

一、TypeHandler

TypeHandler作用

TypeHandler(类型处理器)​ 是 MyBatis 实现 Java 类型与 JDBC 类型之间转换的核心组件。它充当"翻译官"的角色,负责:

  1. 参数设置:将 Java 对象转换为 JDBC 类型并设置到 PreparedStatement中
  2. 结果获取:从 ResultSet或 CallableStatement中取出数据并转换为 Java 对象

内置 TypeHandler 的自动映射

  1. MyBatis 为常见数据类型提供了丰富的内置处理器,实现了"约定优于配置":

    Java 类型JDBC 类型对应 TypeHandler
    StringVARCHARStringTypeHandler
    LongBIGINTLongTypeHandler
    IntegerINTEGERIntegerTypeHandler
    DateTIMESTAMPDateTypeHandler
    LocalDateTimeTIMESTAMPLocalDateTimeTypeHandler
    BooleanBOOLEANBooleanTypeHandler
  2. 为什么大多数情况下,我们在使用mybatis、mybatisplus框架时不需要显式配置TypeHandler?​ 因为 MyBatis 3.4.2 后增强了类型推断能力,在参数非空时能自动选择正确的处理器。比如传入的参数是一个java字符串时,mybatis能通过反射判断这是一个String类型数据,然后会启用StringTypeHandler 这个类型转换器 工作进行数据转换

二、jdbcType 的必要性:处理 NULL 值的核心

  1. 当参数为 null时,MyBatis 无法推断其类型,必须通过 jdbcType明确告知数据库如何处理该 NULL值。这是 JDBC 规范的要求,而非 MyBatis 的"多此一举"。
  2. 因此,如果传参可能为null值时,我们可以显性配置jdbcType
    <!-- 为可能为 NULL 的参数指定 jdbcType --><insertid="insertUser">INSERT INTO user (name, age, email) VALUES ( #{name, jdbcType=VARCHAR}, #{age, jdbcType=INTEGER}, #{email, jdbcType=VARCHAR} )</insert>
  3. jdbcType 和 javaType 会直接影响mybatis框架选择哪个TypeHandler,如果这两个都不配置,mybatis会通过反射判断java 参数类型,进而直接选择TypeHandler,比如说,如果参数类型是字符串Sting,框架会自动选择StringTypeHandler 处理器。如果显性配置了jdbcType,那么框架会选择适配 javaType 和显性配置的jdbcType 的类型处理器TypeHandler,比如java参数类型是String,jdbcType显性配置了bigint类型,那么框架会选择 适配这两个类型的TypeHandler(这种处理器需要自己定义,内置处理器并没有这种类型的)

三、自定义 TypeHandler

  1. 当内置的类型处理器TypeHandler不满足需求时,比如 javatype 为 String 类型,而jdbcType为bigint类型时,就需要我们自己定义一个适配的TypeHandler。

  2. 定义一个TypeHandler,只需要继承 BaseTypeHandler(因为 JavaType 是 String),实现 4 个核心方法,并通过注解绑定 @MappedTypes(JavaType)和 @MappedJdbcTypes(JDBCType)

    importorg.apache.ibatis.type.BaseTypeHandler;importorg.apache.ibatis.type.JdbcType;importorg.apache.ibatis.type.MappedJdbcTypes;importorg.apache.ibatis.type.MappedTypes;importjava.sql.*;/** * 自定义 TypeHandler:处理 JavaType=String ↔ JDBCType=BIGINT 的转换 */// 绑定 Java 类型为 String@MappedTypes(String.class)// 绑定 JDBC 类型为 BIGINT(可指定多个,比如 {JdbcType.BIGINT, JdbcType.INTEGER})@MappedJdbcTypes(JdbcType.BIGINT)publicclassStringToBigIntTypeHandlerextendsBaseTypeHandler<String>{// ========== 【设置参数】Java(String) → 数据库(BIGINT) ==========// 用于 PreparedStatement 设置参数(INSERT/UPDATE/SELECT 传参时)@OverridepublicvoidsetNonNullParameter(PreparedStatementps,inti,Stringparameter,JdbcTypejdbcType)throwsSQLException{// 把 String 类型的参数转为 Long,再设置到 PreparedStatement 中(适配 BIGINT 类型)// 注意:需处理参数为非数字的情况,避免转换异常if(parameter==null||!parameter.matches("\\d+")){thrownewIllegalArgumentException("String 参数必须是数字格式,才能转为 BIGINT,当前值:"+parameter);}LongbigIntValue=Long.parseLong(parameter);ps.setLong(i,bigIntValue);}// ========== 【获取结果】数据库(BIGINT) → Java(String) ==========// 1. 根据列名获取结果(ResultSet.getString(columnName) 本质也是转字符串,这里统一转 Long 再 toString 更严谨)@OverridepublicStringgetNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{Longresult=rs.getLong(columnName);returnrs.wasNull()?null:result.toString();}// 2. 根据列索引获取结果@OverridepublicStringgetNullableResult(ResultSetrs,intcolumnIndex)throwsSQLException{Longresult=rs.getLong(columnIndex);returnrs.wasNull()?null:result.toString();}// 3. 从 CallableStatement(存储过程)获取结果@OverridepublicStringgetNullableResult(CallableStatementcs,intcolumnIndex)throwsSQLException{Longresult=cs.getLong(columnIndex);returncs.wasNull()?null:result.toString();}}
  3. 定义完成之后,我们可以通过yaml全局配置自定义的TypeHandler,如果不想全局配置的话,也可以直接在mybatis中的sql 映射文件中单独配置,局部生效。

  4. 全局配置自定义的TypeHandler

    mybatis:type-handlers-package:com.example.handler# 扫描 TypeHandler 所在包,自动注册

    这样,框架在启动时会加载这个自定义类型处理器,然后会通过 会通过javaType和Jdbctype,自动选择我们定义的类型转换器。

    <!-- Mapper XML 写法 --><insertid="insertUser">INSERT INTO user (id, name) VALUES (#{id, jdbcType=BIGINT}, #{name})</insert>

    对应的mapper接口

    // Mapper 接口publicinterfaceUserMapper{intinsertUser(@Param("id")Stringid,@Param("name")Stringname);}

    mybatisplus 我们可以更方便地直接将jdbcType写入到@Tablefield注解中

    @Data@TableName("user")// 对应数据库表名publicclassUser{@TableField(value="id",jdbcType=JdbcType.BIGINT// 指定 JDBC 类型,在这里可以忽略不写)privateStringid;// Java 类型为 String,对应数据库 BIGINT// 普通字段(无需自定义转换)@TableField("name")privateStringname;}
  5. 我们也可以显性指定类型转换器,使其局部生效

    <resultMapid="userResultMap"type="com.example.entity.User"><!-- 局部指定 TypeHandler --><resultproperty="idStr"column="id"jdbcType="BIGINT"typeHandler="com.example.handler.StringToBigIntTypeHandler"/></resultMap>

    同样的,在 mybatisPlus 框架中的@Tablefield注解中也可以直接指定类型转换器

    @Data@TableName("user")// 对应数据库表名publicclassUser{@TableField(value="id",typeHandler=StringToBigIntTypeHandler.class,// 自定义 TypeHandler)privateStringid;// Java 类型为 String,对应数据库 BIGINT// 普通字段(无需自定义转换)@TableField("name")privateStringname;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/7 17:48:38

百亿订单锁定全球智驾格局,丰田ADAS大单花落博世

作者&#xff1a;钟声编辑&#xff1a;Mark出品&#xff1a;红色星际&#xff08;ID&#xff1a;redplanx&#xff09;头图&#xff1a;丰田汽车图片红色星际小程序/移动端快报据业界人士透露&#xff0c;近期智驾行业堪称“史无前例”的全球订单落地&#xff1a;全球汽车销量常…

作者头像 李华
网站建设 2026/7/7 18:44:35

决策树与回归树简介:原理、实现与应用

文章目录一、决策树基本概念二、决策树分类算法1. ID3算法2. C4.5算法3. CART决策树三、决策树回归模型1. 回归树特点2. 回归树计算示例四、Scikit-learn中的决策树实现1. 分类决策树参数2. 回归决策树参数五、Python实现示例1. 分类决策树实现六、决策树剪枝1. 剪枝的目的2. 剪…

作者头像 李华
网站建设 2026/7/7 3:37:43

java计算机毕业设计宿舍管理信息系统 高校学生宿舍事务一站式平台的设计与实现 基于SpringBoot的校园寝室资源与卫生评比系统

计算机毕业设计宿舍管理信息系统b5ke29 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。迎新高峰&#xff0c;宿管阿姨面前摆着一摞纸质“调宿申请”&#xff0c;楼长拿着 Excel …

作者头像 李华
网站建设 2026/7/7 17:02:32

2025年战略咨询机构对商业未来的思考与塑造

在2025年&#xff0c;战略咨询机构将围绕商业未来的发展趋势展开深入研究。这些机构通过分析市场动态&#xff0c;关注行业变革&#xff0c;帮助企业抓住创新转型的机会。将战略咨询与实际案例结合&#xff0c;能有效揭示企业在面临挑战时的应对策略&#xff0c;包括定制化资源…

作者头像 李华
网站建设 2026/7/7 3:54:17

2025年战略咨询在商业伦理构建中的专业视角

在当今商业场景中&#xff0c;战略咨询为企业提供了关键的伦理框架和实施途径。首先&#xff0c;咨询公司通过深入分析企业的业务模式和市场环境&#xff0c;帮助企业识别其伦理责任与社会影响。其次&#xff0c;通过提供针对性的策略方案&#xff0c;咨询公司促使企业在决策中…

作者头像 李华
网站建设 2026/7/7 17:47:54

搞车十四自由度模型 VS Carsim:联合仿真实战踩坑记录

联合仿真模型验证Carsim车辆动力学模型&#xff08;十四自由度&#xff09; 软件使用&#xff1a;Carsim2019.0Matlab/Simulink 适用场景&#xff1a;采用模块化建模方法&#xff0c;搭建14自由度整车模型&#xff0c;将此模型与carsim进行联合仿真模型验证。 &#xff08;模型…

作者头像 李华