【Mybatis系列】Mybatis之TypeHandler入门

news2024/11/16 17:42:35

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

asp.net mvc游戏门户网站

c#asp.net mvc 说明文档 运行前附加数据库.mdf&#xff08;或sql生成数据库&#xff09; 主要技术&#xff1a; 基于asp.net mvc架构和sql server数据库&#xff0c;并采用EF实体模型开发三层架构BLL DAL 功能模块&#xff1a; 前端展示首页 新闻公告 英雄档案 视频图片 管理…

oracle FUNCTION(任意两个时间 之间的工作小时)

写函数计算 任意两个时间 之间的工作小时 每天工作时间&#xff08;8:00 - 20:00 共12小时&#xff09;&#xff0c;没有休息日 CREATE OR REPLACE FUNCTION SC_YD_DESI.CALCULATE_WORK_HOURS_FUNC (p_current_time IN DATE,p_order_time IN DATE ) RETURN NUMBER ASp_work_hou…

萤石云接口调用

获取appKey和secret 登录后在开发者服务-我的应用中获取 根据appKey和secret获取accessToken 参考官方文档&#xff1a;文档概述 萤石开放平台API文档 # 获取accessToken url_accessToken"https://open.ys7.com/api/lapp/token/get" data {"appKey": &…

选择aspera替代方案的理由,有哪些aspera替代方案

Aspera是一种快速数据传输协议和工具&#xff0c;它使用高效的UDP协议和复杂的流控制算法来实现可靠、高速的数据传输。该协议和工具广泛应用于媒体和娱乐行业、金融服务和其他需要大规模数据传输的领域。然而&#xff0c;Aspera的高昂价格和限制性许可证可能使得某些企业寻找替…

2022年全国硕士研究生入学统一考试管理类专业学位联考英语(二)试题

文章目录 2022年全国硕士研究生招生考试英语&#xff08;二&#xff09;试题Section I Use of EnglishSection II Reading ComprehensionText 12122232425 Text 22627282930 Text 33132333435 Text 43637383940 Section III TranslationSection III WritingPart APart B 2022年…

Python 爬虫 案例 之 豆瓣Top250电影数据

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 课程亮点&#xff1a; 1、动态数据抓包演示 2、csv文件保存 3、requests模块的使用 4、parsel解析数据的使用 环境介绍&#xff1a; python 3.8 pycharm 模块…

在线陪诊系统: 医学科技的革新之路

医疗服务的数字化时代已经到来&#xff0c;而在线陪诊系统正是医学科技革新的杰出代表。通过巧妙的技术代码&#xff0c;这一系统不仅实现了患者和医生之间的远程互动&#xff0c;还将医疗服务推向了一个更加智能化的未来。在这篇文章中&#xff0c;我们将深入探讨在线陪诊系统…

ASP.NET Core Web API设置响应输出的Json数据格式的两种方式

前言 在ASP.NET Core Web API中设置响应输出Json数据格式有两种方式&#xff0c;可以通过添加System.Text.Json或Newtonsoft.JsonJSON序列化和反序列化库在应用程序中全局设置接口响应的Json数据格式&#xff0c;本文示例使用的是新的Minimal API模式。 JSON序列化和反序列化库…

Labview Lite Note

目录 001十六进制字符串转浮点数002浮点数转十六进制字符串 001十六进制字符串转浮点数 002浮点数转十六进制字符串

森林无人机高效解决巡查难题,林区防火掀新篇

山东省某市为了强化森林火灾防范&#xff0c;采用了一项新兴手段——复亚智能无人机森林火情监测系统。这套系统在AI飞行大脑的指挥下&#xff0c;让无人机在空中巡逻&#xff0c;实现了无人机森林防火系统的实施落地。 一、AI大脑如何引领森林无人机高空巡逻&#xff1f; 在山…

区块链存证:杭州互联网法院备选方案之一

文章目录 背景上报的存证系统设计备选方案***总体原则******分层架构******基础节点******存证链******存证业务******存证接入******通用功能******跨链对接架构***业务流程描述用户发起原创内容存证&#xff08;对应上图中左边1,2,3活动&#xff09;发现侵权行为&#xff0c;…

迷你洗衣机哪个牌子好又实惠?小型洗衣机质量排名

随着大家工作的压力越来越大&#xff0c;下了班之后只能想躺平&#xff0c;在洗完澡之后看着还需要手洗的内衣裤真的很头疼。有些小伙伴还有会攒几天再丢进去洗衣机里面一起&#xff0c;而且这样子是非常不好的&#xff0c;用过的内衣裤长时间不清洗容易滋生细菌&#xff0c;而…

HCIP-九、路由控制

九、路由控制 实验拓扑实验需求及解法1.企业生产网运行 OSPF&#xff0c;完成以下需求&#xff1a;2.数据中心运行 ISIS3.路由引入4.路由策略5.策略路由6.ISP 过滤私网路由 实验拓扑 实验需求及解法 1.企业生产网运行 OSPF&#xff0c;完成以下需求&#xff1a; 1.1 OSPF 进程…

Snagit 2024.0.1(Mac屏幕截图软件)

Snagit 2024是一款屏幕截图工具&#xff0c;可以帮助用户轻松捕获、编辑和分享屏幕截图。该工具在Mac上运行&#xff0c;旨在满足用户对于屏幕截图的各种需求。 Snagit 2024支持屏幕录制功能&#xff0c;可以录制摄像头和麦克风等外部设备&#xff0c;让用户录制更加全面的视频…

新农村污水集中处理需要哪些设备

新农村的污水处理问题日益凸显&#xff0c;为了保护农村环境和人民健康&#xff0c;污水集中处理成为一项急需解决的任务。那么&#xff0c;新农村污水集中处理需要哪些设备呢&#xff1f; 首先&#xff0c;污水集中处理系统需要一个有效的污水收集设备。这个设备可以是污水管…

【Linux驱动开发】环境搭建Linux驱动开发环境

环境搭建Linux驱动开发环境 1. 简单描述2. 资源3. 安装4. 基本操作和设置 1. 简单描述 基于讯为电子rk3568教程 2. 资源 下载 VMware Workstation Pro 17 链接 Ubuntu 桌面版&#xff08;64位&#xff09; 链接 3. 安装 需要选择自定义硬件&#xff08;内存大于16g 硬盘500g…

代码随想录算法训练营第35天| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球

JAVA代码编写 860.柠檬水找零 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。你必须…

C++不同平台下的RTTI实现

给定一个含有虚函数的对象的地址&#xff0c;找到对应的类名&#xff0c;不同平台下方法也不同&#xff0c;这是由于RTTI实现并没有统一的标准。 Linux&#xff1a; #include <iostream> #include <typeinfo>class Person { public:virtual void func(){std::cout…

【DeepLearning.AI】吴恩达系列课程——使用Gradio构建AI应用

目录 前言一、Gradio介绍1-1、Gradio介绍1-2、安装1-3、小栗子 二、使用Gradio构建AI应用2-1、NLP任务2-1-1、文本摘要2-1-2、命名实体识别 2-2、聊天任务&#xff08;ChatYuan&#xff09;2-2-1、模型介绍2-2-2、模型下载、参数设置2-2-3、模型测试2-2-4、嵌入到Gradio里2-2-5…

大学生奖学金答辩模板

大学生奖学金答辩模板 前言大学生奖学金答辩模板自制答辩稿 前言 未经同意&#xff0c;请勿转载&#xff0c;请勿商用 这里share 一下近期做的PPT&#xff0c;目前已经抽离成模板&#xff0c;在PPT演讲备注中添加了相关的替换规则及稿子。 这里主要做的是SCUT的模板&#xff0…