【Mybatis系列】Mybatis之TypeHandler入门

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

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

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

博客目录

一.基本介绍

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.启动类

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

2.创建 handler

java 复制代码
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

apl 复制代码
@Mapper
public interface TestMapper extends BaseMapper<TestPO> {
    TestPO selectOne();
}

三.注解方式

1.注解方式

  • autoResultMap:用于自动生成结果映射,而无需手动定义映射关系。
  • typeHandler: 指定类型处理器。
  • @TableName(autoResultMap = true)
  • @TableField(typeHandler = Str2DateTypeHandler.class)
java 复制代码
@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 属性进行类型转换。

apl 复制代码
<!-- 通用查询映射结果 -->
<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 进行测试,方便快捷。

apl 复制代码
@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

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

2.SQL 语句

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

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

3.测试用例

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

apl 复制代码
@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

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

java 复制代码
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.类图关系

觉得有用的话点个赞 👍🏻 呗。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

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

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

相关推荐
aloha_78910 小时前
B站宋红康JAVA基础视频教程(chapter14数据结构与集合源码)
java·数据结构·spring boot·算法·spring cloud·mybatis
狼爷11 小时前
SpringBoot整合MyBatis-Plus
java·mybatis
coffee_baby15 小时前
享元模式详解:解锁高效资源管理的终极武器
java·spring boot·mybatis·享元模式
程序员大金17 小时前
基于SSM+Vue+MySQL的酒店管理系统
前端·vue.js·后端·mysql·spring·tomcat·mybatis
Tatakai251 天前
Mybatis Plus分页查询返回total为0问题
java·spring·bug·mybatis
A_cot1 天前
Redis 的三个并发问题及解决方案(面试题)
java·开发语言·数据库·redis·mybatis
晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑1 天前
苍穹外卖学习笔记(七)
java·windows·笔记·学习·mybatis
二十雨辰2 天前
[苍穹外卖]-12Apache POI入门与实战
java·spring boot·mybatis
Amagi.2 天前
Redis的内存淘汰策略
数据库·redis·mybatis
执键行天涯2 天前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis