【方向盘】MyBatis封装结果集时,Integer类型的id字段被赋值成了Long类型---读源码找原因(下)

简介: 【方向盘】MyBatis封装结果集时,Integer类型的id字段被赋值成了Long类型---读源码找原因(下)

看看我们关心的id属性:


image.png


oh my god。元数据里面保存的根本就不是我们以为的setId(Integer id)这种,而是保留有父类自己的东西。所以我们自然就好理解了,为什么set进去一个BigInteger值竟然也不抱错的原因了(它也继承了Number类)。


到此,我们就算把出现这种现象的原因完全给弄明白了。


but,but,but。这其实并没有彻底的让我“心服口服”,至少有两大问题一直困扰着我,没有找到根本原因。


疑问提出


(此处暂时只提出两个问题做出解答,更加详细的,可以关注后续我的撸管MyBatis源码专题)


1、为何getValue匹配类型转换器的时候,找到的是UnknownTypeHandler?


(本问题此处大概讲一下,更加详细的,MyBatis的类型转换器模式,完全需要拉一个专题出来讲解)


MyBatis内部注册和维护了几乎所有的类型转换器,所以我们平时使用的时候根本就不用管,它自动就能跟我们匹配上,转换成我们需要的结果。在初始化的时候,有个转换器注册类:TypeHandlerRegistry:(列出部分)


image.png


我们会发现3.4版本的MyBatis对 JSR 310标准的日期时间也提供了支持

顺带我们可以看一下,框架升级给我们带来的优雅体验:


image.png


我们发现3.4.6版本处理起来,就优雅很多,大赞。


UnknownTypeHandler对应的类型:


register(Object.class, UNKNOWN_TYPE_HANDLER);
    register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
    register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);


我们会发现,它对应的都是Object类型。


MyBatis在进行初始化的时候,会把所有的xml文件里的ResultMap进行注册,并且提供全局访问。而当注册到此处的继承情况的时候,在获取xml继承的id类型的时候,因为是继承的,所以拿不到实际类型,从而注册不到对应的处理器,最终只能交给UnknownTypeHandler处理


下面一个简单的例子,大家可以感受一下MyBatis为啥注册时候找不到了:


 public static void main(String[] args) throws NoSuchFieldException {
        //Field id = Son.class.getField("id");
        //System.out.println(id); //若id是从父类继承来的,传入的泛型  java.lang.Number com.sayabc.boot2demo1.api.TestController$BaseEntity.id
        //System.out.println(id); //id是本类自己的属性 public java.lang.Integer com.sayabc.boot2demo1.api.TestController$Son.id
        //另外一种方式(属性都是private的都ok)
        Field id = Son.class.getSuperclass().getDeclaredField("id");
        System.out.println(id); //我们会发现获取的SuperClass的  类型直接是java.lang.Number 根本没得商量
    }
    class Son extends BaseEntity<Integer> {
        //public Integer id;
        private String name;
    }
    //此处为了方便反射 属性用public的
    class BaseEntity<PK extends Number> {
        public PK id;
    }


我们能够得出结论。当属性是从父类继承过来的,反射去获取这个字段的类型,它的类型是父类类型。(本例如果没有继承自Number,那返回的就是Object类型)


2、为何刚看到的元数据metaClass对象保存的是父类的setId方法呢?作何考虑?这个值又是什么时候被赋值放进去的呢?


这几个问题其实相对来说比较简单些,如果熟悉流行开源框架的这方面的设计思想,发现都是通的,大家都这么“玩”。因此这个问题我这里就不做解答了,留给读者自己思考一番吧


MyBatis结果集如果是Map遇上泛型的话,也是可能遇上同样问题的。


说到最后


  框架能极大提高我们的开发效率,甚至我们可以基于开源本身定制出更符合我们业务的框架。


一件事本身的复杂度不会减少,它只是从一个地方转移到了另外一个地方而已,总的复杂度是恒定不变的,这是一个定理。


(比如这次的撸源码调试找问题就非常耗时,从开始到搞明白花了整4个小时左右,耗时的原因关键是MyBatis自己存在我上面指出的软病,加大了定位问题的难度)



相关文章
|
3月前
|
SQL Java 数据库连接
MyBatis的配置文件中定义类型别名(type aliases)的技巧。
类型别名提供了一种便捷的方式来引用复杂的全限定类名。通过使用 `<package>`标签进行自动扫描或使用 `<typeAlias>`标签手动指定,可以在整个MyBatis配置中提高清晰度和维护性。无论是简化mapper文件中的配置,还是提高整体的配置可读性,类型别名都是一个非常有用的配置工具。
172 0
|
7月前
|
SQL 存储 Java
Mybatis源码解析:详述初始化过程
以上就是MyBatis的初始化过程,这个过程主要包括SqlSessionFactory的创建、配置文件的解析和加载、映射文件的加载、SqlSession的创建、SQL的执行和SqlSession的关闭。这个过程涉及到了MyBatis的核心类和接口,包括SqlSessionFactory、SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、Configuration、SqlSession和Executor等。通过这个过程,我们可以看出MyBatis的灵活性和强大性,它可以很好地支持定制化SQL、存储过程以及高级映射,同时也避免了几
132 20
|
SQL XML Java
mybatis-源码深入分析(一)
mybatis-源码深入分析(一)
|
12月前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
1808 5
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
148 3
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
257 2
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
363 10
|
XML Java 数据库连接
mybatis源码研究、搭建mybatis源码运行的环境
这篇文章详细介绍了如何搭建MyBatis源码运行的环境,包括创建Maven项目、导入源码、添加代码、Debug运行研究源码,并提供了解决常见问题的方法和链接到搭建好的环境。
mybatis源码研究、搭建mybatis源码运行的环境
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
299 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
732 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码