当前位置: 首页 > news >正文

17. 什么是MyBatis中的TypeHandler?如何自定义TypeHandler处理复杂类型?

TypeHandler 是 MyBatis 中的一个接口,用于在 Java 类型和 JDBC 类型之间进行转换。每当 MyBatis 需要将 Java 对象传递给 SQL 语句,或者从 SQL 查询结果中获取数据并转换为 Java 对象时,都会使用 TypeHandler

TypeHandler 的主要功能包括:

  1. Java 类型到 JDBC 类型的转换:在 MyBatis 执行 SQL 语句时,将 Java 对象作为参数传递给 SQL 语句时,TypeHandler 负责将 Java 类型的数据转换为 JDBC 类型。

  2. JDBC 类型到 Java 类型的转换:在 MyBatis 从数据库中查询数据时,TypeHandler 负责将 JDBC 类型的数据转换为 Java 类型。

MyBatis 内置了一些常用的 TypeHandler,如将 String 转换为 VARCHAR,将 Integer 转换为 INTEGER 等,满足了大多数情况下的需求。然而,对于一些复杂或自定义类型的转换,可能需要自定义 TypeHandler

如何自定义 TypeHandler 处理复杂类型?

当你需要将数据库中的某种数据类型转换为 Java 中的复杂类型,或反过来时,就需要自定义 TypeHandler。以下是自定义 TypeHandler 的步骤和示例。

1. 实现 TypeHandler 接口

MyBatis 提供了 TypeHandler 接口,你可以实现这个接口来自定义类型转换。该接口有四个方法需要实现:

  • setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType):将 Java 类型的数据设置到 PreparedStatement 中,作为 SQL 语句的参数。

  • getResult(ResultSet rs, String columnName):从 ResultSet 中通过列名获取数据,并将其转换为 Java 类型。

  • getResult(ResultSet rs, int columnIndex):从 ResultSet 中通过列索引获取数据,并将其转换为 Java 类型。

  • getResult(CallableStatement cs, int columnIndex):从 CallableStatement 中获取存储过程的输出参数,并将其转换为 Java 类型。

2. 示例:处理复杂 JSON 数据类型

假设你有一个数据库表,其中有一列存储的是 JSON 格式的字符串,但在 Java 中,你希望将它映射为一个 Map<String, Object>

Step 1: 创建一个自定义的 TypeHandler

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
​
import java.sql.*;
​
public class JsonTypeHandler extends BaseTypeHandler<Map<String, Object>> {
​private static final ObjectMapper objectMapper = new ObjectMapper();
​@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Map<String, Object> parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, toJson(parameter));}
​@Overridepublic Map<String, Object> getNullableResult(ResultSet rs, String columnName) throws SQLException {return toMap(rs.getString(columnName));}
​@Overridepublic Map<String, Object> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return toMap(rs.getString(columnIndex));}
​@Overridepublic Map<String, Object> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return toMap(cs.getString(columnIndex));}
​private String toJson(Map<String, Object> map) {try {return objectMapper.writeValueAsString(map);} catch (Exception e) {throw new RuntimeException("Error converting Map to JSON string", e);}}
​private Map<String, Object> toMap(String json) {try {return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});} catch (Exception e) {throw new RuntimeException("Error converting JSON string to Map", e);}}
}
  • toJson():将 Map<String, Object> 转换为 JSON 字符串。

  • toMap():将 JSON 字符串转换为 Map<String, Object>

Step 2: 在 MyBatis 配置文件中注册 TypeHandler

你可以在 MyBatis 的配置文件(mybatis-config.xml)中注册自定义的 TypeHandler

<typeHandlers><typeHandler handler="com.example.JsonTypeHandler" javaType="java.util.Map" jdbcType="VARCHAR"/>
</typeHandlers>

Step 3: 在 Mapper 中使用 TypeHandler

在你的 Mapper 接口中,你可以直接使用这个 TypeHandler 处理相关的字段:

public interface UserMapper {@Select("SELECT id, name, extra_info FROM users WHERE id = #{id}")@Results({@Result(property = "extraInfo", column = "extra_info", typeHandler = JsonTypeHandler.class)})User selectUserById(int id);
}

在这个例子中,数据库中的 extra_info 列是一个 JSON 格式的字符串,而在 Java 对象中,它被映射为 Map<String, Object> 类型。

3. 将 TypeHandler 绑定到具体字段

你也可以在 MyBatis XML 映射文件中,将自定义的 TypeHandler 绑定到具体的字段上:

<resultMap id="UserResultMap" type="com.example.User"><id property="id" column="id"/><result property="name" column="name"/><result property="extraInfo" column="extra_info" typeHandler="com.example.JsonTypeHandler"/>
</resultMap>

总结

  • TypeHandler 的作用TypeHandler 是 MyBatis 用于在 Java 类型和 JDBC 类型之间进行转换的机制,处理复杂类型的转换时非常有用。

  • 自定义 TypeHandler:通过实现 TypeHandler 接口,可以定制 MyBatis 如何将复杂类型与数据库字段进行映射。

  • 使用场景:自定义 TypeHandler 特别适用于处理复杂的数据类型,如 JSON、枚举、自定义对象等。

通过自定义 TypeHandler,你可以使 MyBatis 更加灵活地处理复杂的数据类型,满足特定应用场景下的需求。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CentOS 7 安装yum使用报错:Cannot find a valid baseurl for repo: base/7/x86_6
  • 使用Python中的`zip()`函数
  • WPF的**逻辑树**和**可视树**。
  • ARM 工业计算机搭载 FUXA 组态软件:开启智能制造新时代
  • STL-stack/queue/deque(容器适配器)
  • 直播相关03-录制麦克风声音, ffmpeg 命名,使用命令行完成录音
  • 收藏:不错的中兴的数据治理的PPT
  • framebuffer在Ubuntu上的操作
  • python字典和列表学习
  • Vim编辑器的使用方法
  • 信刻光盘安全隔离与信息交换系统
  • Lvgl8.3 自定义矩形按键的标签,图标 lv_btnmatrix
  • bpftrace使用
  • git 压栈存储当前分支修改,出栈使用保存
  • at:定时任务,仅执行一次
  • CODING 缺陷管理功能正式开始公测
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • passportjs 源码分析
  • python大佬养成计划----difflib模块
  • SegmentFault 2015 Top Rank
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 初识 webpack
  • 第十八天-企业应用架构模式-基本模式
  • 翻译--Thinking in React
  • 解决iview多表头动态更改列元素发生的错误
  • 时间复杂度与空间复杂度分析
  • 手写一个CommonJS打包工具(一)
  • 学习ES6 变量的解构赋值
  • 怎么把视频里的音乐提取出来
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • MyCAT水平分库
  • zabbix3.2监控linux磁盘IO
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • 如何用纯 CSS 创作一个货车 loader
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #pragma预处理命令
  • (2)STL算法之元素计数
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (42)STM32——LCD显示屏实验笔记
  • (待修改)PyG安装步骤
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)http-server应用
  • (转)LINQ之路
  • (转)关于pipe()的详细解析
  • .net开发日常笔记(持续更新)
  • .NET中的十进制浮点类型,徐汇区网站设计