5. MyBatis 如何实现数据库类型和 Java 类型的转换的?

embedded/2024/10/18 4:57:14/

MyBatis 在处理数据库查询结果或传递参数时,需要将数据库类型与 Java 类型之间进行转换。MyBatis 提供了多种方式来实现这种类型转换,主要通过内置的 TypeHandler(类型处理器)机制。

1. TypeHandler 的作用

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

TypeHandler 负责以下两种类型的转换:

  • Java 类型到 JDBC 类型的转换:当 MyBatis 需要将 Java 对象作为参数传递给 SQL 语句时,TypeHandler 会将 Java 类型转换为 JDBC 类型。

  • JDBC 类型到 Java 类型的转换:当 MyBatis 从数据库中获取数据时,TypeHandler 会将 JDBC 类型转换为 Java 类型。

2. 内置的 TypeHandler

MyBatis 提供了许多内置的 TypeHandler,可以处理常见的 Java 类型和 JDBC 类型之间的转换。以下是一些常见的内置 TypeHandler

  • IntegerTypeHandler:用于将 intInteger 转换为数据库中的 INTEGER 类型。

  • StringTypeHandler:用于将 String 转换为数据库中的 VARCHAR 类型。

  • DateTypeHandler:用于将 java.util.Date 转换为数据库中的 DATE 类型。

  • BooleanTypeHandler:用于将 booleanBoolean 转换为数据库中的 BITBOOLEAN 类型。

这些内置的 TypeHandler 在绝大多数情况下能够满足开发者的需求。MyBatis 会自动选择合适的 TypeHandler 来处理常见的数据类型。

3. 自定义 TypeHandler

有时,应用程序中可能需要处理一些自定义的数据类型,或者需要对现有的类型转换进行定制。此时可以通过实现 TypeHandler 接口来自定义类型处理器。

3.1. 实现 TypeHandler 接口

要创建一个自定义的 TypeHandler,你需要实现 org.apache.ibatis.type.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 类型(用于处理存储过程的输出参数)。

3.2. 自定义 TypeHandler 示例

假设你有一个枚举类 Gender,它表示用户的性别。数据库中性别使用 CHAR 类型存储,值为 'M' 或 'F',而在 Java 中使用枚举来表示:

java">public enum Gender {MALE, FEMALE
}

你可以创建一个自定义的 TypeHandler,用于将 CHAR 类型的数据库值转换为 Gender 枚举,并反向转换:

java">import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.*;
​
public class GenderTypeHandler extends BaseTypeHandler<Gender> {
​@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Gender gender, JdbcType jdbcType) throws SQLException {ps.setString(i, gender == Gender.MALE ? "M" : "F");}
​@Overridepublic Gender getNullableResult(ResultSet rs, String columnName) throws SQLException {String gender = rs.getString(columnName);return gender != null && gender.equals("M") ? Gender.MALE : Gender.FEMALE;}
​@Overridepublic Gender getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String gender = rs.getString(columnIndex);return gender != null && gender.equals("M") ? Gender.MALE : Gender.FEMALE;}
​@Overridepublic Gender getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String gender = cs.getString(columnIndex);return gender != null && gender.equals("M") ? Gender.MALE : Gender.FEMALE;}
}

3.3. 注册自定义 TypeHandler

你可以通过两种方式将自定义的 TypeHandler 注册到 MyBatis:

  1. 在 MyBatis 配置文件中注册

    java"><typeHandlers><typeHandler handler="com.example.GenderTypeHandler" javaType="com.example.Gender"/>
    </typeHandlers>
  2. 通过注解注册

    如果你使用 MyBatis 的 Mapper 注解,可以在字段或方法上直接使用 @TypeHandler 注解:

    java">@Select("SELECT id, name, gender FROM users WHERE id = #{id}")
    @Results({@Result(property = "gender", column = "gender", typeHandler = GenderTypeHandler.class)
    })
    User selectUserById(int id);

4. 全局和局部 TypeHandler

  • 全局 TypeHandler:可以通过在 MyBatis 配置文件中注册自定义 TypeHandler,或者使用 @MappedTypes 注解,将自定义 TypeHandler 绑定到特定的 Java 类型。MyBatis 会自动在需要时使用这些全局 TypeHandler

  • 局部 TypeHandler:在特定的 SQL 映射文件或注解中指定 TypeHandler。这种方式仅在指定的地方生效,不会影响全局行为。

5. 总结

  • 内置 TypeHandler:MyBatis 提供了多种内置的 TypeHandler,用于处理常见的 Java 类型和数据库类型之间的转换。

  • 自定义 TypeHandler:当内置的 TypeHandler 不能满足需求时,可以通过实现 TypeHandler 接口或扩展 BaseTypeHandler 类来自定义类型处理器,并在 MyBatis 中注册使用。

  • 注册与使用:自定义的 TypeHandler 可以全局注册,也可以在特定的映射文件或注解中局部使用,灵活处理复杂的类型转换需求。

通过使用 TypeHandler,MyBatis 能够灵活且高效地处理 Java 类型和数据库类型之间的转换,满足各种应用场景的需求。


http://www.ppmy.cn/embedded/105509.html

相关文章

脚手架工具的应用(前端和后端搭建)

前端 一、安装 Node.js 环境 使用npm下载镜像 查看镜像&#xff1a;npm config get registry 切换淘宝镜像&#xff1a;npm config set registry https://registry.npmmirror.com 还原镜像&#xff1a;npm config set registry https://registry.npmjs.org 二、使用 Vue.js 脚…

Python大数据之Hadoop学习——day06_hive内外部表

一.hive内外表操作 1. 建表语法 create [external] table [if not exists] 表名(字段名 字段类型 ,字段名 字段类型,...) [partitioned by (分区字段名 分区字段类型)] # 分区表固定格式 [clustered by (分桶字段名) into 桶个数 buckets] # 分桶表固定格式 [so…

<数据集>车辆识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;3002张 标注数量(xml文件个数)&#xff1a;3002 标注数量(txt文件个数)&#xff1a;3002 标注类别数&#xff1a;21 标注类别名称&#xff1a;[ambulance, army vehicle, auto rickshaw, bicycle, bus, car, garba…

Java JVM 垃圾回收算法详解

Java 虚拟机&#xff08;JVM&#xff09;是运行 Java 应用程序的核心&#xff0c;它的垃圾回收&#xff08;Garbage Collection, GC&#xff09;机制是 JVM 中非常重要的一个部分。垃圾回收的主要任务是自动管理内存&#xff0c;回收那些不再被使用的对象&#xff0c;从而释放内…

git修改提交名字

大家在使用git的时候&#xff0c;有的时候可能不是使用自己的账号&#xff0c;或者说账号的信息不符合自己的预期&#xff0c;具体表现在什么地方呢&#xff1f;在提交代码的时候&#xff0c;名字不是自己的&#xff0c;或者是名字不是自己想要的。 下面就是如何查看和修改。 …

C#复习之封装_静态成员

知识点一 静态成员的基本概念 知识点二 早已出现的静态成员 知识点四 静态成员的使用 知识点五 为什么可以直接点出来 //记住&#xff01; //程序中是不能无中生有的 //我们要使用的对象&#xff0c;变量&#xff0c;函数都是要在内存中分配内存空间的 //之所以要实例化对象…

【教程】MySQL数据库学习笔记(六)——数据查询语言DQL(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【MySQL数据库学习】系列文章 第一章 《认识与环境搭建》 第二章 《数据类型》 第三章 《数据定义语言DDL》 第四章 《数据操…

51单片机.之 UART串口

备 注&#xff1a;只当接收到大写字符’B’后改变蜂鸣器的开/关状态 /* ******************************************************************************* * 《手把手教你学51单片机(C语言版)》 * 配套 KST-51 单片机开发板 示例源…