mybatis源码学习-1-调试环境

写在前面,这里会有很多借鉴的内容,有以下三个原因

  1. 本博客只是作为本人学习记录并用以分享,并不是专业的技术型博客
  2. 笔者是位刚刚开始尝试阅读源码的人,对源码的阅读流程乃至整体架构并不熟悉,观看他人博客可以帮助我快速入门
  3. 如果只是笔者自己观看,难免会有很多弄不懂乃至理解错误的地方,观看他人的体会能有效改善这个问题

1. 依赖工具

  1. Maven
  2. Git
  3. Idea

2. 源码拉取

从官方仓库 https://github.com/mybatis/mybatis-3 Fork 出属于自己的仓库。

本文使用的 MyBatis 版本为 3.5.0-SNAPSHOT

3. 调试

这里(下面所有内容)仅仅是用于调试环境,请不用着急于在这里就弄懂调用流程

MyBatis 想要调试,非常方便,只需要打开 org.apache.ibatis.autoconstructor.AutoConstructorTest 单元测试类,任意一个单元测试方法,右键,开始调试即可。

当然,考虑到让大家更好的理解 AutoConstructorTest 这个类,下面,我们还是详细解析下。AutoConstructorTest 所在在 autoconstructor 包下,整体结构如下:

包结构图

4. mybatis-config.xml

mybatis-config.xml ,MyBatis 配置文件。XML 如下:

<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- autoMappingBehavior should be set in each test case --><environments default="development"><environment id="development"><!-- 配置事务管理 --><transactionManager type="JDBC"><property name="" value=""/></transactionManager><!-- 配置数据源  --><dataSource type="UNPOOLED"><property name="driver" value="org.hsqldb.jdbcDriver"/><property name="url" value="jdbc:hsqldb:mem:automapping"/><property name="username" value="sa"/></dataSource></environment></environments><!-- 扫描 Mapper 文件  --><mappers><mapper resource="org/apache/ibatis/autoconstructor/AutoConstructorMapper.xml"/></mappers></configuration>
  • <environments /> 标签中,配置了事务管理和数据源。考虑到减少外部依赖,所以使用了 HSQLDB 。
  • <mappers /> 标签中,配置了需要扫描的 Mapper 文件。目前,仅仅扫描 AutoConstructorMapper.xml 文件。

5. AutoConstructorMapper.xml

AutoConstructorMapper.xml ,Mapper 文件。代码如下:

<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="org.apache.ibatis.autoconstructor.AutoConstructorMapper">
</mapper>
  • 对应的接口为 org.apache.ibatis.autoconstructor.AutoConstructorMapper

5.1 AutoConstructorMapper

public interface AutoConstructorMapper {// ========== PrimitiveSubject ==========@Select("SELECT * FROM subject WHERE id = #{id}")PrimitiveSubject getSubject(final int id);@Select("SELECT * FROM subject")List<PrimitiveSubject> getSubjects();// ========== AnnotatedSubject ==========@Select("SELECT * FROM subject")List<AnnotatedSubject> getAnnotatedSubjects();// ========== BadSubject ==========@Select("SELECT * FROM subject")List<BadSubject> getBadSubjects();// ========== ExtensiveSubject ==========@Select("SELECT * FROM extensive_subject")List<ExtensiveSubject> getExtensiveSubject();}
  • 使用注解的方法,编写 SQL 。

6. CreateDB.sql

CreateDB.sql 文件,用于单元测试里,初始化数据库的数据。如下:

DROP TABLE subject
IF EXISTS;DROP TABLE extensive_subject
IF EXISTS;CREATE TABLE subject (id     INT NOT NULL,name   VARCHAR(20),age    INT NOT NULL,height INT,weight INT,active BIT,dt     TIMESTAMP
);CREATE TABLE extensive_subject (aByte      TINYINT,aShort     SMALLINT,aChar      CHAR,anInt      INT,aLong      BIGINT,aFloat     FLOAT,aDouble    DOUBLE,aBoolean   BIT,aString    VARCHAR(255),anEnum     VARCHAR(50),aClob      LONGVARCHAR,aBlob      LONGVARBINARY,aTimestamp TIMESTAMP
);INSERT INTO subject VALUES(1, 'a', 10, 100, 45, 1, CURRENT_TIMESTAMP),(2, 'b', 10, NULL, 45, 1, CURRENT_TIMESTAMP),(2, 'c', 10, NULL, NULL, 0, CURRENT_TIMESTAMP);INSERT INTO extensive_subject
VALUES(1, 1, 'a', 1, 1, 1, 1.0, 1, 'a', 'AVALUE', 'ACLOB', 'aaaaaabbbbbb', CURRENT_TIMESTAMP),(2, 2, 'b', 2, 2, 2, 2.0, 2, 'b', 'BVALUE', 'BCLOB', '010101010101', CURRENT_TIMESTAMP),(3, 3, 'c', 3, 3, 3, 3.0, 3, 'c', 'CVALUE', 'CCLOB', '777d010078da', CURRENT_TIMESTAMP);
  • 创建了 subject 表,并初始化三条数据。
  • 创建了 extensive_subject 表,并初始化三条数据。

7. POJO

在 AutoConstructorMapper 中,我们可以看到有四个 POJO 类。但是,从 CreateDB.sql 中,实际只有两个表。这个是为什么呢?继续往下看噢。

7.1 AnnotatedSubject

package org.apache.ibatis.autoconstructor;import org.apache.ibatis.annotations.AutomapConstructor;public class AnnotatedSubject {private final int id;private final String name;private final int age;private final int height;private final int weight;public AnnotatedSubject(final int id, final String name, final int age, final int height, final int weight) {this.id = id;this.name = name;this.age = age;this.height = height;this.weight = weight;}@AutomapConstructorpublic AnnotatedSubject(final int id, final String name, final int age, final Integer height, final Integer weight) {this.id = id;this.name = name;this.age = age;this.height = height == null ? 0 : height;this.weight = weight == null ? 0 : weight;}}
  • 对应 subject 表。
  • @AutomapConstructor注解,表示 MyBatis 查询后,在创建 AnnotatedSubject 对象,使用该构造方法。
    • 😈 实际场景下,非常少使用这个注解,甚至 Google 上资料也不多。

7.1.1 PrimitiveSubject

package org.apache.ibatis.autoconstructor;import java.util.Date;public class PrimitiveSubject {private final int id;private final String name;private final int age;private final int height;private final int weight;private final boolean active;private final Date dt;public PrimitiveSubject(final int id, final String name, final int age, final int height, final int weight, final boolean active, final Date dt) {this.id = id;this.name = name;this.age = age;this.height = height;this.weight = weight;this.active = active;this.dt = dt;}}
  • 对应的也是 subject 表。
  • 和 AnnotatedSubject 不同,在其构造方法上,weightheight 方法参数的类型是 int ,而不是 Integer 。那么,如果 subject 表中的记录,这两个字段为 NULL 时,会创建 PrimitiveSubject 对象报错。

7.1.2 BadSubject

package org.apache.ibatis.autoconstructor;public class BadSubject {private final int id;private final String name;private final int age;private final Height height;private final Double weight;public BadSubject(final int id, final String name, final int age, final Height height, final Double weight) {this.id = id;this.name = name;this.age = age;this.height = height;this.weight = weight == null ? 0 : weight;}private class Height {}}
  • 对应的也是 subject 表。
  • 和 AnnotatedSubject 不同,在其构造方法上,height 方法参数的类型是 Height ,而不是 Integer 。因为 MyBatis 无法识别 Height 类,所以会创建 BadSubject 对象报错。

老艿艿:一般情况下,POJO 对象里,不使用基本类型。

7.2 ExtensiveSubject

package org.apache.ibatis.autoconstructor;public class ExtensiveSubject {private final byte aByte;private final short aShort;private final char aChar;private final int anInt;private final long aLong;private final float aFloat;private final double aDouble;private final boolean aBoolean;private final String aString;// enum typesprivate final TestEnum anEnum;// array types// string to lob types:private final String aClob;private final String aBlob;public ExtensiveSubject(final byte aByte,final short aShort,final char aChar,final int anInt,final long aLong,final float aFloat,final double aDouble,final boolean aBoolean,final String aString,final TestEnum anEnum,final String aClob,final String aBlob) {this.aByte = aByte;this.aShort = aShort;this.aChar = aChar;this.anInt = anInt;this.aLong = aLong;this.aFloat = aFloat;this.aDouble = aDouble;this.aBoolean = aBoolean;this.aString = aString;this.anEnum = anEnum;this.aClob = aClob;this.aBlob = aBlob;}public enum TestEnum {AVALUE, BVALUE, CVALUE;}}
  • 对应的也是 extensive_subject 表。
  • 这是个复杂对象,基本涵盖了各种类型的数据。

8. AutoConstructorTest

org.apache.ibatis.autoconstructor.AutoConstructorTest ,单元测试类。

8.1 setUp

private static SqlSessionFactory sqlSessionFactory;@BeforeClass
public static void setUp() throws Exception {// create a SqlSessionFactory// 创建 SqlSessionFactory 对象,基于 mybatis-config.xml 配置文件。try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/autoconstructor/mybatis-config.xml")) {sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);}// populate in-memory database// 初始化数据到内存数据库,基于 CreateDB.sql SQL 文件。BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),"org/apache/ibatis/autoconstructor/CreateDB.sql");
}
  • 创建 SqlSessionFactory 对象,基于 mybatis-config.xml 配置文件。
  • 初始化数据到内存数据库,基于 CreateDB.sql SQL 文件。

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

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

相关文章

Spring源码解析-总览

1、前言 Spring源码一直贯穿我们Java的开发中&#xff0c;只要你是一个Java开发人员就一定知道Spring全家桶。Spring全家桶为我们一共一站式服务&#xff0c;IOC、AOP更是Spring显著特性。但是Spring到底怎么为我们提供容器&#xff0c;管理资源的呢&#xff1f;下来&#xff0…

Ubuntu学习---跟着绍发学linux课程记录(第二部分)

文章目录 7 文件权限7.1 文件的权限7.2 修改文件权限7.3 修改文件的属主 8、可执行脚本8.2Shell脚本8.3python脚本的创建 9Shell9.1Shell中的变量9.2 环境变量9.3用户环境变量 学习链接: Ubuntu 21.04乌班图 Linux使用教程_60集Linux课程 所有资料在 http://afanihao.cn/java …

学生管理系统VueAjax版本

学生管理系统VueAjax版本 使用Vue和Ajax对原有学生管理系统进行优化 1.准备工作 创建AjaxResult类&#xff0c;对Ajax回传的信息封装在对象中 package com.grg.Result;/*** Author Grg* Date 2023/8/30 8:51* PackageName:com.grg.Result* ClassName: AjaxResult* Descript…

Java抛出异常

当某个方法抛出了异常时&#xff0c;如果当前方法没有捕获异常&#xff0c;异常就会被抛到上层调用方法&#xff0c;直到遇到某个try ... catch被捕获为止 调用printStackTrace()可以打印异常的传播栈&#xff0c;对于调试非常有用&#xff1b;捕获异常并再次抛出新的异常时&am…

项目-IM

tim-server tim-server启动类实现CommandLineRunner接口&#xff0c;重写run()方法 run()方法开启一个线程&#xff0c;创建zk持久父节点&#xff0c;创建临时顺序子节点&#xff0c;将netty-server信息写入 1.1 用户登录 1.2 gateway向认证授权中心请求token 1.3 从zookee…

在windows上安装Cmake软件

Cmake是一个跨语言、跨平台、开源的编译工具&#xff0c;可以编译C、C、Note.js、JavaScript、C#、Java、Python、Php、Object-C、Ruby等工程&#xff0c;需要设置对应的src源码目录、ext第三方依赖目录、CMakeList.txt构建列表&#xff0c;再使用cmake命令即可。     2023年…

程序员自由创业周记#2:前期准备

感恩 上次公开了创业的决定后&#xff0c;得到了很多亲朋好友和陌生朋友的鼓励或支持&#xff0c;以不同的形式&#xff0c;感动之情溢于言表。这些都会记在心里&#xff0c;大恩不言谢~ 创业方向 笔者是一名资质平平的iOS开发程序猿&#xff0c;创业项目也就是开发App卖&am…

Jmeter(二十九):Jmeter常用场景梳理

一、每秒钟固定调用次数 如果想控制每秒发送请求数量,仅仅通过线程数与循环次数是不够的,因为这只能控制发送总数,而要控制每秒发送数量,需要线程数与常数吞吐量控制器的搭配使用,这种场景在性能测试中使用不多。 例如每秒钟调用30次接口,那么把线程数设置为30,将常数…

Netty-ChannelPipeline

EventLoop可以说是 Netty 的调度中心&#xff0c;负责监听多种事件类型&#xff1a;I/O 事件、信号事件、定时事件等&#xff0c;然而实际的业务处理逻辑则是由 ChannelPipeline 中所定义的 ChannelHandler 完成的&#xff0c;ChannelPipeline 和 ChannelHandler应用开发的过程…

C语言(第三十三天)

3.1.2 画图推演 3.2 举例2&#xff1a;顺序打印一个整数的每一位 输入一个整数m&#xff0c;打印这个按照顺序打印整数的每一位。 比如&#xff1a; 输入&#xff1a;1234 输出&#xff1a;1 2 3 4 输入&#xff1a;520 输出&#xff1a;5 2 0 3.2.1 分析和代码实现 这个题目&a…

数据结构--队列与循环队列

队列 队列是什么&#xff0c;先联想一下队&#xff0c;排队先来的人排前面先出&#xff0c;后来的人排后面后出&#xff1b;队列的性质也一样&#xff0c;先进队列的数据先出&#xff0c;后进队列的后出&#xff1b;就像图一的样子&#xff1a; 图1 如图1&#xff0c;1号元素是…

本地开机启动jar

1&#xff1a;首先有个可运行的jar包 本地以ruiyi代码为例打包 2&#xff1a;编写bat命令---命名为.bat即可 echo off java -jar D:\everyDay\test\RuoYi\target\RuoYi.jar 3&#xff1a;设置为开机自启动启动 快捷键winr----输入shell:startup---打开启动文档夹 把bat文件复…

春秋云镜 CVE-2018-16283

春秋云镜 CVE-2018-16283 WordPress Plugin Wechat Broadcast LFI 靶标介绍 WordPress Plugin Wechat Broadcast LFI 启动场景 漏洞利用 exp # Exploit Title: WordPress Plugin Wechat Broadcast 1.2.0 - Local File Inclusion # Author: Manuel Garcia Cardenas # Date:…

Spring boot 第一个程序

新建工程 选择spring-boot版本 右键创建类TestController&#xff1a; 代码如下&#xff1a; package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springf…

Empowering Long-tail Item Recommendation through Cross Decoupling Network (CDN)

Empowering Long-tail Item Recommendation through Cross Decoupling Network (CDN) 来源&#xff1a; KDD’2023Google Research 文章目录 Empowering Long-tail Item Recommendation through Cross Decoupling Network (CDN)长尾问题分析CDNItem Memorization and General…

是否在业务中使用大语言模型?

ChatGPT取得了巨大的成功&#xff0c;在短短一个月内就获得了1亿用户&#xff0c;并激发了企业和专业人士对如何在他们的组织中利用这一工具的兴趣和好奇心。 但LLM究竟是什么&#xff0c;它们如何使你的企业受益?它只是一种炒作&#xff0c;还是会长期存在? 在这篇文章中我…

从零开始的Hadoop学习(六)| HDFS读写流程、NN和2NN工作机制、DataNode工作机制

1. HDFS的读写流程&#xff08;面试重点&#xff09; 1.1 HDFS写数据流程 1.1.1 剖析文件写入 &#xff08;1&#xff09;客户端通过 Distributed FileSystem 模块向 NameNode 请求上传文件&#xff0c;NameNode检查目标文件是否已存在&#xff0c;父目录是否存在。 &#x…

springsecurity+oauth 分布式认证授权笔记总结12

一 springsecurity实现权限认证的笔记 1.1 springsecurity的作用 springsecurity两大核心功能是认证和授权&#xff0c;通过usernamepasswordAuthenticationFilter进行认证&#xff1b;通过filtersecurityintercepter进行授权。springsecurity其实多个filter过滤链进行过滤。…

Google Services Framework 谷歌服务框架的安装以及遇到的常见问题

安装谷歌三件套&#xff1a; 1、Google 服务框架&#xff08;Google Services Framework&#xff09;下载地址&#xff1a; https://www.apkmirror.com/apk/google-inc/google-services-framework/ 注意一定要选择与自己手机对应的安卓系统版本的服务框架。 2、Google Play Se…

Java设计模式:四、行为型模式-05:备忘录模式

文章目录 一、定义&#xff1a;备忘录模式二、模拟场景&#xff1a;备忘录模式三、改善代码&#xff1a;备忘录模式3.1 工程结构3.2 备忘录模式模型结构图3.3 备忘录模式定义3.3.1 配置信息类3.3.2 备忘录类3.3.3 记录者类3.3.4 管理员类 3.4 单元测试 四、总结&#xff1a;备忘…