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

【Mybatis】TypeHandler使用

引言

在使用MyBatis进行项目开发时,我们经常会遇到Java类型与数据库类型不匹配的情况。为了解决这一问题,MyBatis提供了一个强大的机制——TypeHandlerTypeHandler是MyBatis中一个用于处理Java类型和数据库类型转换的组件,它在MyBatis进行参数设置和结果映射时起着至关重要的作用。本文将详细介绍TypeHandler的使用方法,包括自定义TypeHandler的创建和注册,以及在实际项目中的应用示例。

TypeHandler基础

什么是TypeHandler

在MyBatis中,TypeHandler用于处理Java类型和JDBC类型之间的映射和转换。每当MyBatis在执行SQL操作时,都会使用TypeHandler来确保数据类型的正确转换。

TypeHandler的工作原理

当MyBatis从数据库读取数据时,TypeHandler负责将数据库类型转换为Java类型;反之,当MyBatis向数据库写入数据时,它将Java类型转换为数据库类型。这一过程对于开发者是透明的,由MyBatis框架内部自动完成。

TypeHandler的应用

内置TypeHandler

MyBatis已经为我们提供了一系列内置的TypeHandler,用于处理常见的Java类型与数据库类型之间的转换。例如,IntegerTypeHandlerStringTypeHandler等。

自定义TypeHandler

尽管MyBatis提供了很多内置的TypeHandler,但在某些特殊情况下,我们可能需要自定义TypeHandler来处理特定的类型转换。自定义TypeHandler可以让我们控制复杂类型的持久化策略,例如枚举类型、复杂的对象类型等。

创建自定义TypeHandler

创建一个自定义的TypeHandler首先需要实现MyBatis的TypeHandler接口或者继承BaseTypeHandler类。以下是一个简单的自定义TypeHandler示例,用于转换枚举类型:

public enum EnumType {ACTIVE("A"),DISABLED("D"),DELETED("X");private final String code;EnumType(String code) {this.code = code;}public String getCode() {return code;}public static EnumType fromCode(String code) {for (EnumType status : EnumType.values()) {if (status.getCode().equals(code)) {return status;}}throw new IllegalArgumentException("Unknown code: " + code);}
}
public class MyEnumTypeHandler extends BaseTypeHandler<EnumType> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, EnumType parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter.getCode());}@Overridepublic EnumType getNullableResult(ResultSet rs, String columnName) throws SQLException {String code = rs.getString(columnName);return EnumType.fromCode(code);}@Overridepublic EnumType getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String code = rs.getString(columnIndex);return EnumType.fromCode(code);}@Overridepublic EnumType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String code = cs.getString(columnIndex);return EnumType.fromCode(code);}
}

在上述代码中,EnumType是一个枚举类型,我们通过覆写BaseTypeHandler的方法来实现自定义的类型转换逻辑。

注册自定义TypeHandler

自定义的TypeHandler创建完成后,需要在MyBatis配置文件中进行注册才能使用。可以通过以下两种方式注册自定义TypeHandler

  • 在MyBatis全局配置文件mybatis-config.xml中注册:
<typeHandlers><typeHandler handler="com.example.MyEnumTypeHandler"/>
</typeHandlers>
  • 使用注解直接在Mapper方法上指定使用的TypeHandler
@Select("SELECT * FROM some_table WHERE column = #{enumValue,typeHandler=com.example.MyEnumTypeHandler}")
SomeObject selectByEnumValue(EnumType enumValue);

实际应用示例

接下来,我们将通过一个实际的示例来展示如何在项目中应用自定义TypeHandler

假设我们有一个用户表(user),其中有一个枚举类型的字段用于表示用户状态(status)。我们可以使用上面创建的MyEnumTypeHandler来处理这个字段的读写操作。

public class User {private Integer id;private String name;private String email;private EnumType status; // 使用EnumType枚举表示用户状态// 构造函数public User() {}// Getter和Setter方法public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public EnumType getStatus() {return status;}public void setStatus(EnumType status) {this.status = status;}// 有toString()、equals()和hashCode()方法
}

Mapper接口

public interface UserMapper {@Select("SELECT * FROM user WHERE id = #{id}")@Results({@Result(property = "status", column = "status", typeHandler = MyEnumTypeHandler.class)})User selectById(int id);@Insert("INSERT INTO user(name, status) VALUES(#{name}, #{status, typeHandler=com.example.MyEnumTypeHandler})")void insertUser(User user);
}

使用TypeHandler进行查询和插入

使用UserMapper接口,我们可以很容易地插入和查询具有枚举类型字段的用户记录。

User user = new User();
user.setName("Alice");
user.setStatus(EnumType.ACTIVE);
userMapper.insertUser(user);User dbUser = userMapper.selectById(user.getId());
System.out.println(dbUser.getStatus()); // 输出 ACTIVE

通过上述示例,我们可以看到自定义TypeHandler在处理枚举类型字段时的强大功能和灵活性。

TypeHandler接口

TypeHandler接口定义在org.apache.ibatis.type包中,它定义了几个核心的方法,这些方法用于将Java类型转换为JDBC类型,以及将JDBC类型转换回Java类型。以下是TypeHandler接口的一个基本概述:

public interface TypeHandler<T> {void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;T getResult(ResultSet rs, String columnName) throws SQLException;T getResult(ResultSet rs, int columnIndex) throws SQLException;T getResult(CallableStatement cs, int columnIndex) throws SQLException;}
  • setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType): 该方法用于在PreparedStatement中设置参数。它将Java类型转换为一个可以在SQL查询中使用的JDBC类型。
  • getResult(ResultSet rs, String columnName): 从ResultSet中获取名为columnName的列的值,并将其转换为Java类型。
  • getResult(ResultSet rs, int columnIndex): 从ResultSet中获取指定列索引的值,并将其转换为Java类型。
  • getResult(CallableStatement cs, int columnIndex): 从CallableStatement中获取指定列索引的值,并将其转换为Java类型。

BaseTypeHandler抽象类

BaseTypeHandlerTypeHandler接口的一个抽象实现,提供了一些实用的方法简化了自定义TypeHandler的开发。大多数自定义TypeHandler都会继承这个类,因为它实现了TypeHandler接口的大部分通用逻辑,让开发者只需关注于特定类型转换的实现。BaseTypeHandler提供的一些方法包括:

public abstract class BaseTypeHandler<T> implements TypeHandler<T> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {// 实现类需要覆盖这个方法来设置非空参数}@Overridepublic T getNullableResult(ResultSet rs, String columnName) throws SQLException {// 实现类需要覆盖这个方法来获取可能为空的结果}@Overridepublic T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {// 实现类需要覆盖这个方法来获取可能为空的结果}@Overridepublic T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {// 实现类需要覆盖这个方法来获取可能为空的结果}}

我们实现自定义TypeHandler时,通常会继承BaseTypeHandler类,并实现上述的setNonNullParametergetNullableResult方法来处理具体的类型转换逻辑。

结语

MyBatis的TypeHandler是一个强大的机制,它为我们提供了一种灵活的方式来处理Java类型与数据库类型之间的转换。通过使用内置的TypeHandler或创建自定义的TypeHandler,我们可以轻松地解决在实际开发中遇到的类型不匹配问题。希望本文能够帮助读者更好地理解和使用MyBatis中的TypeHandler

相关文章:

【Mybatis】TypeHandler使用

引言 在使用MyBatis进行项目开发时&#xff0c;我们经常会遇到Java类型与数据库类型不匹配的情况。为了解决这一问题&#xff0c;MyBatis提供了一个强大的机制——TypeHandler。TypeHandler是MyBatis中一个用于处理Java类型和数据库类型转换的组件&#xff0c;它在MyBatis进行…...

[计算机网络]---网络编程套接字

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、基础知识…...

分布式文件系统 SpringBoot+FastDFS+Vue.js【二】

分布式文件系统 SpringBootFastDFSVue.js【二】 六、实现上传功能并展示数据6.1.创建数据库6.2.创建spring boot项目fastDFS-java6.3.引入依赖6.3.fastdfs-client配置文件6.4.跨域配置GlobalCrosConfig.java6.5.创建模型--实体类6.5.1.FastDfsFile.java6.5.2.FastDfsFileType.j…...

开源软件:推动软件行业繁荣的力量

文章目录 &#x1f4d1;引言开源软件的优势分析开放性与透明度低成本与灵活性创新与协作 开源软件对软件行业的影响推动技术创新和进步促进软件行业的合作与交流培养人才和提高技能促进软件行业的可持续发展 结语 &#x1f4d1;引言 随着信息技术的飞速发展&#xff0c;软件已经…...

[杂记]mmdetection3.x中的数据流与基本流程详解(数据集读取, 数据增强, 训练)

之前跑了一下mmdetection 3.x自带的一些算法, 但是具体的代码细节总是看了就忘, 所以想做一些笔记, 方便初学者参考. 其实比较不能忍的是, 官网的文档还是空的… 这次想写其中的数据流是如何运作的, 包括从读取数据集的样本与真值, 到数据增强, 再到模型的forward当中. 0. MMDe…...

阿里云香港轻量应用服务器怎么样,建站速度快吗?

阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品&#xff0c;中国电信CN2高速网络高质量、大规格BGP带宽&#xff0c;运营商精品公网直连中国内地&#xff0c;时延更低&#xff0c;优化海外回中国内地流量的公网线路&#xff0c;可以提高国际业务访问质量。阿里云服务…...

事务及在SpringBoot项目中使用的两种方式

1.事务简介 事务&#xff08;transaction&#xff09;是访问并可能操作各种数据项的一个数据库操作序列&#xff0c;这些操作要么全部执行&#xff0c;要么全部不执行&#xff0c;是一个不可分割的工作单位。 事物的四大特性: 原子性&#xff08;Atomicity&#xff09;&#xf…...

stm32--笔记

一、引脚与变量 ​​​​​​​​​​​​​​ 二、STM32时钟 [STM32-时钟系统详解_stm32时钟_KevinFlyn的博客-CSDN博客] 三、定时器中断实验 1、定时器中断实验 ​ stm32关于通用定时器的周期、频率计算公式_stm32tim频率计算_胶囊咖啡的博客-CSDN博客 ​ 【STM32】通用…...

2024前端面试准备之CSS篇(二)

全文链接 1. 什么是伪类和伪元素 伪类(Pseudo-class): 伪类是选择器的一种,用于选择特定状态或条件下的元素。它们以冒号(:)开头,用于向选择器添加额外的特定条件。例如,:hover伪类用于选择鼠标悬停在元素上的状态,:nth-child(n)伪类用于选择父元素下的第n个子元素等。…...

轨道交通信号增强与覆盖解决方案——经济高效,灵活应用于各类轨道交通场景!

方案背景 我国是世界上轨道交通里程最长的国家&#xff0c;轨道交通也为我们的日常出行带来极大的便利。伴随着无线通信技术的快速发展将我们带入电子时代&#xff0c;出行的过程中对无线通信的依赖程度越来越高&#xff0c;无论是车站还是车内都需要强大、高质量的解决方案以…...

学习数据接构和算法的第10天

题目讲解 尾插 #include <stdio.h> #include <stdlib.h> // 定义顺序表结构 #define MAX_SIZE 100 struct ArrayList {int array[MAX_SIZE];int size; // 当前元素个数 }; // 初始化顺序表 void init(struct ArrayList *list) {list->size 0; // 初始时元素个…...

初识KMP算法

目录 1.KMP算法的介绍 2.next数组 3.总结 1.KMP算法的介绍 首先我们会疑惑&#xff0c;什么是KMP算法&#xff1f;这个算法是用来干什么的&#xff1f; KMP&#xff08;Knuth-Morris-Pratt&#xff09;算法是一种用于字符串匹配的经典算法&#xff0c;它的目标是在一个主文本…...

Javaweb之SpringBootWeb案例之AOP概述及入门的详细解析

2.1 AOP概述 什么是AOP&#xff1f; AOP英文全称&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程、面向方面编程&#xff09;&#xff0c;其实说白了&#xff0c;面向切面编程就是面向特定方法编程。 那什么又是面向方法编程呢&#xff0c;为什么又需要面向…...

【Java代码洁癖】NO.2 单元测试mock显式赋值,不能忍

反例 RunWith(MockitoJunitRunner.class) public class Test {Mockpublic SomeBean someBean new SomeBean(); } 正例 RunWith(MockitoJunitRunner.class) public class Test {Mockpublic SomeBean someBean ; } 解读 使用Mock注解的对象不应该被显式赋值&#xff0c;应当…...

2024.2.19

使用fread和fwrite完成两个文件的拷贝 #include<stdio.h> #include<stdlib.h> #include<string.h> int main(int argc, const char *argv[]) {FILE *fpNULL;if((fpfopen("./tset.txt","w"))NULL){perror("open error");retur…...

B端系统升级方案模板:针对美观性和体验性升级(总体方案)

大家好&#xff0c;我是大美B端工场&#xff0c;专注于前端开发和UI设计&#xff0c;有需求可以私信。本篇从全局分享如何升级B端系统&#xff0c;搞B端系统升级的有个整体思维&#xff0c;不是说美化几个图标&#xff0c;修改几个页面就能解决的&#xff0c;这个方案模板&…...

第九篇:node静态文件服务(中间件)

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! &#x1f4d8; 引言&#xff1a; 当今互联网时代&am…...

软件测试-功能测试-测试流程-如何进行需求评审?对于测试人员来讲,如何从测试的角度评审需求文档?

导言 产品人员编写的需求文档&#xff0c;无疑是一个项目或者一项新功能的开端。需求文档的优劣&#xff0c;直接影响开发人员的代码质量&#xff0c;更会影响到后续的测试工作。所以&#xff0c;我认为&#xff0c;需求评审对于开发质量以及测试质量至关重要&#xff0c;那么…...

无刷电机驱动详解

无刷电机驱动详解 有刷电机和无刷电机字面上理解最大的区别就是有无电刷&#xff0c;实际上区别还有换向器&#xff0c;电刷和换向器的作用是什么&#xff1f;电刷负责在旋转部件与静止部件之间传导电流&#xff0c;换向器则利用旋转惯性周期性的改变线圈中电流的方向。 所以…...

Linux+Win双系统远程重启到Win

背景 电脑安装了双系统&#xff08;ubuntu 22.04 win11&#xff09;&#xff0c;默认进入ubuntu系统。给电脑设置了WoL(Wake-on-LAN)&#xff0c;方便远程开机远程控制。 但是ubuntu的引导程序grub无法远程控制&#xff0c;远程开机会默认进入ubuntu。 虽然说可以进入ubuntu后…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...