【Mybatis系列】Mybatis之TypeHandler入门

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

博客目录

    • 一.基本介绍
      • 1.什么是 TypeHandler?
      • 2.BaseTypeHandler 使用场景?
      • 3.BaseTypeHandler 常用方法?
    • 二.基础代码
      • 1.启动类
      • 2.创建 handler
      • 3.mapper
    • 三.注解方式
      • 1.注解方式
      • 2.resultMap 配置
      • 3.测试
    • 四.全局配置方式
      • 1.全局配置方式
      • 2.SQL 语句
      • 3.测试用例
    • 五.源码分析
      • 1.BaseTypeHandler
      • 2.setNonNullParameter
      • 3.getNullableResult(接受列名参数)
      • 4.getNullableResult(接受列索引参数)
      • 5.getNullableResult 方法(接受 CallableStatement 参数)
      • 6.类图关系

一.基本介绍

1.什么是 TypeHandler?

“TypeHandler” 通常指的是在软件开发中处理数据类型转换和操作的组件或模块。具体来说,TypeHandler 主要用于将一个数据类型转换为另一个数据类型,以便在不同的上下文中使用。

在不同的编程语言和框架中,TypeHandler 的实现方式可能有所不同。以下是一些常见的情况:

  1. 数据库中的 TypeHandler: 在持久化层,比如与数据库的交互中,TypeHandler 可能用于将数据库中的数据类型与应用程序中的数据类型进行映射。例如,将数据库中的字符串字段映射为应用程序中的整数类型。

  2. Web 开发中的 TypeHandler: 在处理用户输入或从网络传输数据时,可能需要将字符串转换为数字、日期等。TypeHandler 在这种情况下可以用于验证和转换数据类型。

  3. 对象关系映射 (ORM) 中的 TypeHandler: 在使用 ORM 框架时,TypeHandler 通常用于将数据库中的数据类型映射到编程语言中的数据类型。这是因为数据库和编程语言之间可能存在类型差异,需要进行适当的转换。

  4. 用户界面 (UI) 层中的 TypeHandler: 当用户与应用程序的用户界面交互时,输入数据通常以字符串形式提供。TypeHandler 在这里可以用于将用户输入的字符串转换为应用程序内部需要的数据类型。

TypeHandler 在软件开发中扮演着一个数据类型转换和操作的角色,有助于确保不同部分之间的数据一致性和正确性。具体实现方式取决于应用程序的需求和使用的技术栈。

2.BaseTypeHandler 使用场景?

org.apache.ibatis.type.BaseTypeHandler 是 MyBatis 中的一个抽象基类,用于简化自定义类型处理器(TypeHandler)的实现。MyBatis 是一个支持持久化的 Java 持久层框架,而类型处理器用于处理 Java 对象与数据库中的数据类型之间的映射关系。

BaseTypeHandler 提供了一些默认的实现,减少了自定义类型处理器的工作量。

3.BaseTypeHandler 常用方法?

如果你想自定义一个类型处理器,可以继承 BaseTypeHandler 并实现其中的一些方法。以下是 BaseTypeHandler 中的一些关键方法和其作用:

  1. setNonNullParameter 方法:

    • 用于将 Java 类型的非空参数设置到 PreparedStatement 对象中。
    • 子类需要实现此方法以指定如何将 Java 类型的非空参数设置到 PreparedStatement 中。
  2. getNullableResult 方法:

    • 从 ResultSet 中获取指定列的值,以及从 CallableStatement 中获取指定参数的值。
    • 子类需要实现此方法以指定如何从数据库结果集中获取数据。
  3. setNonNullParameter 方法:

    • 将非空的 Java 对象设置到 PreparedStatement 中。
    • 子类需要实现此方法以指定如何将 Java 对象设置到 PreparedStatement 中。
  4. getNullableResult 方法:

    • 从 ResultSet 中获取指定列的值,以及从 CallableStatement 中获取指定参数的值。
    • 子类需要实现此方法以指定如何从数据库结果集中获取数据。

通过继承 BaseTypeHandler,你可以只关注需要自定义的转换逻辑,而无需实现所有的方法。这样,你可以更方便地创建自己的类型处理器,用于处理特定类型的数据映射。

需要注意的是,MyBatis 也提供了一些预定义的类型处理器,用于处理常见的数据类型,如字符串、整数、日期等。但在某些情况下,你可能需要创建自己的类型处理器以处理特定的需求或自定义数据类型。

二.基础代码

1.启动类

@SpringBootApplication
public class AppRun {
    public static void main(String[] args) {
        SpringApplication.run(AppRun.class, args);
    }
}

2.创建 handler

public class Str2DateTypeHandler extends BaseTypeHandler<Date> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, date2Str(parameter));
    }

    @Override
    public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return str2Date(rs.getString(columnName));
    }

    @Override
    public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return str2Date(rs.getString(columnIndex));
    }

    @Override
    public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return str2Date(cs.getString(columnIndex));
    }

    private static Date str2Date(String str) {
        if (str == null || str.trim().length() == 0) return null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(str);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String date2Str(Date date) {
        if (date == null) return null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.format(date);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3.mapper

@Mapper
public interface TestMapper extends BaseMapper<TestPO> {
    TestPO selectOne();
}

三.注解方式

1.注解方式

  • autoResultMap:用于自动生成结果映射,而无需手动定义映射关系。
  • typeHandler: 指定类型处理器。
  • @TableName(autoResultMap = true)
  • @TableField(typeHandler = Str2DateTypeHandler.class)
@Data
@TableName(value = "test", autoResultMap = true)
public class TestPO implements Serializable {
    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.NONE)
    private String id;

    @TableField(typeHandler = Str2DateTypeHandler.class)
    private Date date;
}

2.resultMap 配置

如果返回值是 resultMap 类型,可以通过配置 resultMap 中列的 typeHandler 属性进行类型转换。

<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="org.example.pojo.TestPO">
    <id column="id" property="id"/>
    <result column="date" property="date" typeHandler="org.example.typehandler.Str2DateTypeHandler"/>
</resultMap>

3.测试

使用 CommandLineRunner 进行测试,方便快捷。

@Component
public class TestRunner implements CommandLineRunner {

    @Autowired
    private TestMapper testMapper;

    @Override
    public void run(String... args) throws Exception {
        List<TestPO> list = this.testMapper.selectList(null);
        System.out.println(list.get(0).getId() + " - " + list.get(0).getDate());
    }
}

四.全局配置方式

1.全局配置方式

设置类型处理的包路径: type-handlers-package

mybatis-plus:
  mapper-locations: classpath*:mapper/*Mapper.xml
  configuration:
    cache-enabled: true
  type-handlers-package: org.example.typehandler

2.SQL 语句

数据库 date 是 String 类型,PO 定义的是 Date 类型,直接查询数据是会报错的。

<select id="selectOne" resultType="org.example.pojo.TestPO">
    SELECT id, date
    FROM test limit 1;
</select>

3.测试用例

使用 CommandLineRunner 进行测试,方便快捷。

@Component
public class TestRunner2 implements CommandLineRunner {

    @Autowired
    private TestMapper testMapper;

    @Override
    public void run(String... args) throws Exception {
        TestPO testPO = this.testMapper.selectOne();
        System.out.println(testPO.getId() + " - " + testPO.getDate());
    }
}

五.源码分析

1.BaseTypeHandler

需要重写的四个方法如下:

public abstract void setNonNullParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;

public abstract T getNullableResult(ResultSet var1, String var2) throws SQLException;

public abstract T getNullableResult(ResultSet var1, int var2) throws SQLException;

public abstract T getNullableResult(CallableStatement var1, int var2) throws SQLException;

2.setNonNullParameter

作用: 该方法用于将 Java 类型的非空参数设置到 PreparedStatement 对象中,以便将数据插入到数据库中。

参数:

  • var1:表示要设置参数的 PreparedStatement 对象。
  • var2:表示要设置的参数的位置。
  • var3:表示要设置的非空参数值,即从 Java 对象映射到数据库中的数据。
  • var4:表示 JDBC 类型,用于指定参数的数据类型。

异常: 抛出 SQLException,以处理可能的数据库操作异常。

3.getNullableResult(接受列名参数)

作用: 该方法从 ResultSet 中获取指定列的值,并将其映射为 Java 对象,处理可空的查询结果。

参数:

  • var1:表示要获取数据的 ResultSet 对象。
  • var2:表示要获取的列的名称。

返回值: 返回映射到 Java 对象的可空结果。

异常: 抛出 SQLException,以处理可能的数据库操作异常。

4.getNullableResult(接受列索引参数)

作用: 该方法从 ResultSet 中获取指定列的值,并将其映射为 Java 对象,处理可空的查询结果。

参数:

  • var1:表示要获取数据的 ResultSet 对象。
  • var2:表示要获取的列的索引。

返回值: 返回映射到 Java 对象的可空结果。

异常: 抛出 SQLException,以处理可能的数据库操作异常。

5.getNullableResult 方法(接受 CallableStatement 参数)

作用: 该方法从 CallableStatement 中获取指定位置的值,并将其映射为 Java 对象,处理可空的查询结果。

参数:

  • var1:表示要获取数据的 CallableStatement 对象。
  • var2:表示要获取的位置。

返回值: 返回映射到 Java 对象的可空结果。

异常: 抛出 SQLException,以处理可能的数据库操作异常。

6.类图关系

image-20231128122432039

觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/195545.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】深入理解数据类型转换与运算

文章目录 1.数据类型转换在分析源程序之前&#xff0c;我们需要了解几个基本概念&#xff1a;现在来分析源程序中的变量及其对应的十进制真值以及扩展操作方式&#xff1a; 1.1. short si -32768;1.2. unsigned short usi si;1.3. int i si;1.4. unsigned ui usi; 2&#x…

U-Net及其变体在医学图像分割中的应用研究综述

U-Net及其变体在医学图像分割中的应用研究综述 论文来自&#xff1a;中国生物医学工程学报 2022 摘 要&#xff1a; 医学图像分割可以为临床诊疗和病理学研究提供可靠的依据&#xff0c;并能辅助医生对病人的病情做出准确的判断。 基于深度学习的分割网络的出现解决了传统自动分…

Git——Git应用入门

将会介绍以下知识&#xff1a; 搭建Git环境和创建Git版本库&#xff08;init、clone&#xff09;。文件添加、状态检查、创建注释和查看历史记录。与其他Git版本库交互&#xff08;pull、push&#xff09;。解决合并冲突。创建分支列表、列表切换和合并。创建标签。 1、版本控…

sqli-labs靶场详解(less17-less22)

目录 less-17 less-18 less-19 less-20 less-21 less-22 less-17 修改密码关卡 服务器后端 账号密码都存在数据库中 使用UPDATE进行修改密码 尝试username处 尝试好久尝试不出来应该是对用户名进行了过滤 于是对password进行注入 判断注入点 passwdadmin 报错&#xff1a…

vue3中的customRef创建一个自定义的 ref对象

customRef 创建一个自定义的 ref&#xff0c;并对其依赖项跟踪和更新触发进行显式控制 小案例: 自定义 ref 实现 debounce <template><div style"font-size: 14px;"><input v-model"text" placeholder"搜索关键字"/><…

智能优化算法应用:基于郊狼算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于郊狼算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于郊狼算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.郊狼算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

深思:C与C++相互调用问题

背景 上周&#xff0c;偶然看到同事愁眉苦脸的样子&#xff0c;便善意咨询了下发生了什么。简单沟通下&#xff0c;才知道他遇到了一个工程编译的问题&#xff0c;一直无法编译通过&#xff0c;困扰了他快一天时间。出于个人的求知欲和知识的渴望&#xff0c;我便主动与他一同分…

PHP中关于func_get_args()方法

首先呢这个函数出现的是比较早的,大致应该是PHP4出现的, func_get_args — 返回一个包含函数参数列表的数组 说明 func_get_args(): array 获取函数参数列表的数组。 该函数可以配合 func_get_arg() 和 func_num_args() 一起使用&#xff0c;从而使得用户自定义函数可以接…

基于C#实现块状链表

在数据结构的世界里&#xff0c;我们会认识各种各样的数据结构&#xff0c;每一种数据结构都能解决相应领域的问题&#xff0c;当然每个数据结构&#xff0c;有他的优点&#xff0c;必然就有它的缺点&#xff0c;那么如何创造一种数据结构来将某两种数据结构进行扬长避短&#…

【数据结构/C++】栈和队列_循环队列

牺牲一个存储单元来判断队满。 #include<iostream> using namespace std; // 循环队列 #define MaxSize 10 typedef int ElemType; typedef struct {ElemType data[MaxSize];int front, rear; } SqQueue; // 初始化队列 void InitQueue(SqQueue &Q) {// 判断队空 Q.…

微服务知识大杂烩

1.什么是微服务? 微服务(Microservices)是一种软件架构风格,将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能,并通过轻量级通信机制(如HTTP)相互协作。每个微服务可以独立开发、部署和扩展,使得应用程序更加灵活、可伸缩和可…

Milvus入门手册1.0

一、window环境搭建&#xff08;单机&#xff09; 1、docker安装 略 2、milvus安装 参考文档&#xff1a;https://milvus.io/docs/install_standalone-docker.md tips: &#xff08;1&#xff09;compose.yaml下载比较慢&#xff0c;可以在网络上找一份。 &#xff08;2&…

2023-11-26 LeetCode每日一题(统计子串中的唯一字符)

2023-11-26每日一题 一、题目编号 828. 统计子串中的唯一字符二、题目链接 点击跳转到题目位置 三、题目描述 我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符&#xff0c;并返回唯一字符的个数。 例如&#xff1a;s “LEETCODE” &#xff0c;则其…

Python字典合并

合并两个有部分key相同的字典&#xff0c;相同key保留两个字典中对应key的较大值。 (笔记模板由python脚本于2023年11月27日 18:12:15创建&#xff0c;本篇笔记适合熟悉Python字典的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Fr…

通过预定义颜色查找表上色_vtkLookupTable_vtkColorTransferFunction

开发环境&#xff1a; Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题&#xff1a;通过颜色查找表给vtkPlaneSource上色 第一种技术是使用预定义颜色的查找表vtkLookupTable。这包括创建一个查找表并为其分配一组已命名的…

攻关眼科难题!第一届爱尔眼科-四川大学科研基金完成立项

当前我国眼科患者数量不断增长&#xff0c;人民群众对高质量的眼健康的需要不断攀升&#xff0c;而目前国内眼科医疗资源远不能满足需求&#xff0c;疑难眼病诊疗能力及学术科研体系建设仍有较大进步空间。基于此&#xff0c;爱尔眼科携手四川大学共同设立爱尔眼科-四川大学科研…

js moment时间范围拿到中间间隔时间

2023.11.27今天我学习了如何对只返回的开始时间和结束时间做处理&#xff0c;比如后端返回了&#xff1a; [time:{start:202301,end:202311}] 我们需要把中间的间隔渲染出来。 [202301,202302,202303,202304,202305,202306,202307,202308,202309,202310,202311] 利用moment…

搭建你自己的网盘-个人云存储的终极解决方案-nextcloud AIO(二)

今天接着上篇&#xff0c;我们继续来玩nextcloud AIO. 当我们看到这个页面的时候&#xff0c;则证明AIO已经安装好了&#xff0c;登录账号和密码在图上已经标注了。点击open your nextcloud 即可跳转到我们的域名的登录页。 输入用户名和密码后登录即可。 打开前台页面&#x…

【Dockerfile】将自己的项目构建成镜像部署运行

目录 1.Dockerfile 2.镜像结构 3.Dockerfile语法 4.构建Java项目 5.基于Java8构建项目 1.Dockerfile 常见的镜像在DockerHub就能找到&#xff0c;但是我们自己写的项目就必须自己构建镜像了。 而要自定义镜像&#xff0c;就必须先了解镜像的结构才行。 2.镜像结构 镜…

element table滚动条失效

问题描述:给el-table限制高度之后滚动条没了 给看看咋设置的&#xff1a; <el-table:data"tableData"style"width: 100%;"ref"table"max-height"400"sort-change"changeSort">对比了老半天找不出问题&#xff0c;最后…