手写mybatis之通过注解配置执行SQL语句

news2024/10/24 4:27:17

前言


可能领导也都觉得可能就是码农不爱说话,其实不爱说话是一方面,但还有另外一方面是有些领导对于码农提出的问题,给出的回复往往是:“你提出这个问题,你就要给出这个问题的解决办法!”
所以不同的岗位要执行各自的职责,无论领导、产品、研发、测试、业务,都应该环环相扣,各司其职,不过分包装结果,正确看待问题。才可能做出像苹果那样的优秀产品,而不是那么割裂的独立功能。
目标
在日常业务需求开发中,研发人员使用 Mybatis 框架的时候,除了可以基于 Mapper XML 方式配置执行 SQL 信息以外,也可以通过注解的方式在 DAO 接口方法上配置执行 SQL 语句。
大部分时候一些研发规范中,都比较倾向于将 SQL 语句维护在 XML 中,因为这样可以进行统一管理,也能在发包后需要做一些修改 SQL 配置进行测试和验证时,基于 XML 配置变更 SQL 语句。如果是基于方法注解那么就需要重新打包,上传部分文件或者全部文件,才能进行这样的验证了。
如下的用法
在这里插入图片描述
对应研发人员来说,日常使用 Mybatis 框架,对于 XML 和注解配置也都是可以共用的,主要基于配置文件 mappers 中,引入的是哪类资源。
在之前本章节之前我们只实现了 mapper 中是 resource=“mapper/User_Mapper.xml” 的配置类型,那么本章节因为需要支持注解配置 SQL 语句,所以这里还需要支持 class=“com.lm.mybatis.test.dao.IUserDao” 这样配置到 DAO 接口类上的方式,解析 SQL 语句。

设计
那么这一部分的代码逻辑变动,主要以 XMLConfigBuilder 配置构建器的 Mapper 解析开始,因为只有从这里开始才是判断一个 Mapper 到底是使用了 XML 配置还是注解配置。
在这里插入图片描述
通过注解配置执行SQL语句核心类关系。
在这里插入图片描述
XMLConfigBuilder 配置构建器是解析 Mapper 的入口,以这条流程线中的方法 mapperElement 开始,处理 XML 解析的基础上,扩展注解的解析处理。
那么这里会通过从 xml 读取到的 class 配置,通过 Configuration 配置项类的添加 Mapper 方法,启动解析注解类语句的操作。也就是在 MapperRegistry 映射器注册机,随着 Configuration 配置项调用 addMapper 时所做的注解解析操作。
1:脚本语言驱动器
LanguageDriver 脚本语言驱动,是我们在前面章节已经实现的功能,给配置在 Mapper XML 中的 SQL 语句进行解析创建 SqlSource 信息使用的。接口如下;
在这里插入图片描述
从方法的入参可以看到,script 的参数是 Element 用于解析 XML 文件的,那么本章节为了可以处理注解类型的 SQL 配置,则需要添加新的接口方法。

在这里插入图片描述
通过重载一个 createSqlSource 接口,把 script 的入参设置为 String 类型,来解析注解 SQL 的配置。具体的接口实现如下;
在这里插入图片描述
用于解析注解方式的 createSqlSource 方法,其与 XML 解析来说,更加简单了。因为这里不需要提供专门的 XML 脚本构建器。而是直接按照 SQL 的入参信息,创建 RawSqlSource 即可。
另外这里相对 Mybatis 源码是省略了部分流程的,把核心结构展示给读者。在学习的过程中掌握了主链路以后,也可以参照源码,来学习这部分的实现细则。
注解配置构建器
在 Mybatis 框架的实现中,有专门一个 annotations 注解包,来提供用于配置到 DAO 方法上的注解,这些注解包括了所有的增删改查操作,同时可以设定一些额外的返回参数等。
定义注解
本章节主要以带着读者贯穿整个使用注解下,Mybatis 对此类配置的处理和执行过程,所以我们这里只添加四个注解 @Insert、@Delete、@Update、@Select
在这里插入图片描述
在 Mybatis 框架中除了以上这四个注解,还有如;@Arg、@InsertProvider、@Param、@ResultMap 等注解参数配置。读者学习本章节以后,可以尝试参照 Mybatis 源码添加其他注解功能的开发,学习整个流程的处理过程。
配置解析
加载配置注解和提供解析方法
在这里插入图片描述
自定义注解的解析配置,主要在 MapperAnnotationBuilder 类中完成,整个类在构造函数中配置需要解析的注解,并提供解析方法处理语句的解析。而这个类的解析操作,基本都是基于 Method 来获取参数类型、返回类型、注解方法等,完成解析过程。
解析语句 Statement
在这里插入图片描述
整个解析的核心流程包括;根据 Method#getParameterTypes 方法获取入参类型、从 Configuration 配置项中获取默认的 LanguageDriver 脚本语言驱动、以及基于注解所提供的配置信息,也就是 value 值中的 SQL 来创建 SqlSource 语句。
Mapper XML 解析调用
注解配置、解析处理,这些工作完成以后,接下来就是把解析放到哪一环来处理了。在 Mybatis 的源码中,是基于 XML 配置构建器解析 Mapper 时候进行判断处理,是 xml 还是注解。如果是注解则会调用到 MapperRegistry#addMapper 方法,并开始执行解析注解的相关操作。
在这里插入图片描述
在 XMLConfigBuilder 配置构建器的 Mapper 解析处理中,根据从 XML 配置获取到的 resource、class 分别进行判断解析。
如果 resource 为空,mapperClass 不为空,则进行注解的解析处理。在这段代码中则是根据 mapperClass 获取对应的接口,并通过 Configuration#addMapper 方法,添加到配置项中。而这个 Mapper 的添加会调用到 MapperRegistry 进而调用注解解析操作。
解析注解调用
在这里插入图片描述
以 XMLConfigBuilder#mapperElement 解析调用 configuration.addMapper 方法开始,则会调用到 mapperRegistry.addMapper(type); 方法。那么接下来就到了处理注解类解析的操作。在这里插入图片描述

在 addMapper 方法中,根据 Class 注册完映射器代理工厂后,则开始进行解析注解操作。这部分 MapperAnnotationBuilder 类的功能在前面已经讲解,到这里就把整个流程串联起来了。
测试
建一个数据库名称为 mybatis 并在库中创建表 user 以及添加测试数据,如下.

CREATE TABLE
    USER
    (
        id bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
        userId VARCHAR(9) COMMENT '用户ID',
        userHead VARCHAR(16) COMMENT '用户头像',
        createTime TIMESTAMP NULL COMMENT '创建时间',
        updateTime TIMESTAMP NULL COMMENT '更新时间',
        userName VARCHAR(64),
        PRIMARY KEY (id)
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
insert into user (id, userId, userHead, createTime, updateTime, userName) values (1, '10001', '1_04', '2022-04-13 00:00:00', '2022-04-13 00:00:00', '小傅哥');    

配置数据源

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </dataSource>
    </environment>
</environments>

通过 mybatis-config-datasource.xml 配置数据源信息,包括:driver、url、username、password
在这里 dataSource 可以按需配置成 DRUID、UNPOOLED 和 POOLED 进行测试验证。
配置Mapper加载方式

<mappers>
    <!-- XML 配置
    <mapper resource="mapper/User_Mapper.xml"/>
    -->
    <!--注解配置-->
    <mapper class="cn.bugstack.mybatis.test.dao.IUserDao"/>
</mappers>

在前面章节都是通过 resource 方式配置 Mapper XML,本章节这里可以把这部分注释掉。通过 class 配置出 DAO 接口即可。
配置注解

public interface IUserDao {

    @Select("SELECT id, userId, userName, userHead\n" +
            "FROM user\n" +
            "where id = #{id}")
    User queryUserInfoById(Long id);

    @Select("SELECT id, userId, userName, userHead\n" +
            "        FROM user\n" +
            "        where id = #{id}")
    User queryUserInfo(User req);

    @Select("SELECT id, userId, userName, userHead\n" +
            "FROM user")
    List<User> queryUserInfoList();

    @Update("UPDATE user\n" +
            "SET userName = #{userName}\n" +
            "WHERE id = #{id}")
    int updateUserInfo(User req);

    @Insert("INSERT INTO user\n" +
            "(userId, userName, userHead, createTime, updateTime)\n" +
            "VALUES (#{userId}, #{userName}, #{userHead}, now(), now())")
    void insertUserInfo(User req);

    @Insert("DELETE FROM user WHERE userId = #{userId}")
    int deleteUserInfoByUserId(String userId);

}

单元测试

@Test
public void test_insertUserInfo() {
    // 1. 获取映射器对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);

    // 2. 测试验证
    User user = new User();
    user.setUserId("10002");
    user.setUserName("小白");
    user.setUserHead("1_05");
    userDao.insertUserInfo(user);
    logger.info("测试结果:{}", "Insert OK");

    // 3. 提交事务
    sqlSession.commit();
}

测试结果
在这里插入图片描述
查询测试(多条数据)

@Test
public void test_queryUserInfoList() {
    // 1. 获取映射器对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);
    // 2. 测试验证:对象参数
    List<User> users = userDao.queryUserInfoList();
    logger.info("测试结果:{}", JSON.toJSONString(users));
}

修改测试

@Test
public void test_updateUserInfo() {
    // 1. 获取映射器对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);
    // 2. 测试验证
    int count = userDao.updateUserInfo(new User(1L, "10001", "叮当猫"));
    logger.info("测试结果:{}", count);
    // 3. 提交事务
    sqlSession.commit();
}

删除测试

@Test
public void test_deleteUserInfoByUserId() {
    // 1. 获取映射器对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);
    // 2. 测试验证
    int count = userDao.deleteUserInfoByUserId("10002");
    logger.info("测试结果:{}", count == 1);
    // 3. 提交事务
    sqlSession.commit();
}

总结
本章节在原有解析 Mapper XML 的基础上扩展了使用注解方式的解析和处理,让整个框架功能更加完善。同时在扩展注解功能的结构时候,可以看到整个整合过程并不复杂,更多是类似模块式的拼装,通过开发出一个注解解析构建器,并在 Mapper 注册过程中完成调用和解析操作。所以如果一个框架的整体设计是完善的,那么在功能的迭代和添加过程中也会是非常清晰容易的。

好了到这里就结束了手写mybatis之通过注解配置执行SQL语句的学习,大家一定要跟着动手操作起来。需要源码的 可si我获取;

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

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

相关文章

AD24之铺铜操作

1.选择板框&#xff0c;即机械1层&#xff0c;转换为覆铜 这样顶层就铺好了&#xff0c;还需要铺底层 2.打开底层&#xff0c;选择板框&#xff0c;转换为铺铜&#xff0c;然后给铜皮添加网络和层&#xff0c;最后是铺铜 注意&#xff1a;None铺铜是无效果的&#xff0c;要Ha…

2.使用 Label Studio 标注文本

使用 Label Studio 标注文本 文章目录 使用 Label Studio 标注文本前言Label Studio的简单使用1.创建项目2.添加本地存储3.选择标注模板4.添加数据5.标注6.添加关系 总结 前言 Label Studio是一个开源的功能强大的标注平台&#xff0c;可以标注视频&#xff0c;图片&#xff0…

一个新韭菜的炒股心得

一个新韭菜的炒股心得 前言 股市其实是一场修行。时刻控制人性的弱点。所以量化优势明显&#xff0c;它没有情绪&#xff0c;可以随意止盈止损。我从一个小白一路走过来&#xff0c;发现A股里有学不完的知识,有做不完的功课。我的主要关注点在如何有效实现价值投资(价值投资在…

算法: 位运算题目练习

文章目录 位运算判定字符是否唯一丢失的数字两整数之和只出现一次的数字 II消失的两个数字常见位运算总结 位运算 判定字符是否唯一 有很多解法,比如hash表,或者给字符串排个序,然后遍历… 写这道题时没注意到如果出现奇数个相同字符,此时就应该返回false了. 而不是全部放到位…

智慧高铁站的概念与优势

1. 概念介绍 智慧高铁站是指利用先进的信息技术和智能化手段&#xff0c;对高铁站的运营管理、服务功能、安全保障等方面进行全面升级和优化的现代化交通枢纽。通过数字化、网络化和智能化技术的应用&#xff0c;实现高铁站的智能化管理、便捷化服务和可持续发展&#xff0c;从…

【Linux】Linux进程基础

1.进程介绍与概念 进程的本质是在计算机内存中运⾏的程序&#xff0c;但是这⼀个概念太过于⼴泛 每个应用程序运行于现代操作系统之上时&#xff0c;操作系统会提供一种抽象&#xff0c;好像系统上只有这个程序在运行&#xff0c;所有的硬件资源都被这个程序在使用。这种假象…

ui自动化知识点-web端

UI &#xff1a; User Interface( ⽤户接⼝ - ⽤户界⾯ ) &#xff0c;主要包括&#xff1a; app 、 web ui ⾃动化测试&#xff1a;使⽤⼯具或代码执⾏⽤例的过程 什么样的项⽬适合做⾃动化&#xff1a;1、需要回归测试项⽬&#xff08;甲⽅⾃营项⽬、⾦融、电商&#xff09…

鸿蒙开发 三十七 ArkTs类 class 构造函数

语法格式如下&#xff1a; class 类名{ 字段1:类型 字段2:类型 constructor(参数...) { this.字段 参数 } } 实例化&#xff1a; const 实例1 new 类名(参数...&#xff09;每new一次就去执行一次constructor方法&#xff0c;创建不同的实例。 每次new都要传参数&…

MySQL学习笔记(持续更新,目前到十一章锁)

1、Mysql概述 1.1 数据库相关概念 三个概念&#xff1a;数据库、数据库管理系统、SQL 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase&#xff08;DB&#xff09;数据库管理系统操纵和管理数据库的大型软件DataBase Mangement System&#xf…

C++ -string -常见用法1

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【C】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 文章目录 &#x1f4a1;前言1.构造函数1.1函数原型1.2用法速览1.3详解() -重点⭐( s) -重点⭐( n, c) -重点⭐( str) -重点⭐( str, pos, len)( s, n) 2.容量函数2.1函数原型2…

github 上将 stable 合并到 master 分支步骤

本地仓库分支&#xff1a;origin 远端仓库分支&#xff1a;upstream 切到非 master 分支上&#xff0c;比如 dev # 本地操作 git branch -D master git fetch upstream master::master git checkout master # 这步是拉取远端 stable 到 master 上&#xff0c;可能会出错误 # fa…

21次惊艳亮相!凯特王妃的秋季时尚造型!在时尚领域她已经无限接近戴安娜王妃

虽然凯特米德尔顿正式成为英国王室成员才刚刚十多年&#xff0c;但很难想象没有她的王室会是什么样子。毕竟&#xff0c;凭借她非凡的风格和不可否认的魅力&#xff0c;威尔士王妃在2011年迅速赢得了我们以及全世界的喜爱。 我们都喜欢关注她的项目以及她和威廉王子的爱情故事…

基于STM32的智能电能表设计

引言 本项目设计了一个基于STM32的智能电能表&#xff0c;能够实时测量电压、电流、功率以及累计的电能消耗。通过ADC模块采集电压和电流信号&#xff0c;结合功率计算算法&#xff0c;系统可以精准地监控家庭或工业设备的电能消耗。该智能电能表还支持远程数据传输和本地数据…

Krea.ai正式发布AI视频集合站:Luma、Runway与可灵的深度整合

引言 在数字内容日益丰富的今天&#xff0c;视频制作的需求呈现爆发式增长。为了满足创作者对高效、创新视频工具的渴求&#xff0c;Krea.ai推出了全新的AI视频集合站。此平台整合了多款领先工具&#xff0c;如Luma、Runway、可灵和Minimax&#xff0c;为用户提供一站式的视频…

【等号绕过】

简介 一、大小于号绕过 上面的<>是不等于的意思 测试注入点&#xff1a; id1 正常输入id1 测试是否有注入id1 and 11%23 提示hacker~ 被过滤了id1 and 1%23 没有被过滤&#xff0c;说明是被过滤&#xff0c;但是没有输出id1 and 1%23 页面有输…

25四非网安保研回忆录(北航网安/东南网安/重大计科等)

目录 0 个人情况 1 夏令营 西南大学计科 西南交通大学计科 重庆大学计科 2 预推免 东南大学网安 北京航空航天大学网安 3 写在最后 0 个人情况 计算机类比较强的四非&#xff0c;信安专业rank1&#xff0c;六级540&#xff0c;竞赛十几个&#xff0c;无论文&#xff…

【Linux网络编程】网络基础 | Socket 编程基础

&#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系列 &#x1f308;Linux学习专栏&#xff1a; 南桥谈Linux &#x1f308;数据结构学习专栏&#xff1a; 数据结构杂谈 &#x1f308;数据…

2.13寸电子墨水屏HINK-E0213+esp8266

记录好数字 2.13寸电子墨水屏HINK-E0213esp8266 声明:大部分资料来源于微雪电子http://微雪电子-官网 https://www.waveshare.net/ 前言 很久以前买的一块电子墨水屏,运气很好,这个型号HINK-E0213资料很全,而且微雪官网也有相关电路资料http://2.13inch e-Paper HAT - Waves…

java邮件发送

文章目录 前言一、开启SMTP邮箱配置二、spring-mail1.引入依赖2.yml配置3.使用二、hutool-mail1.引入hutool2.在resource下新增mail.setting3.使用总结前言 发送邮件: 目前比较简单的有两种方式实现: spring-mailhuool-mail现在看下两种方式 一、开启SMTP邮箱配置 两种方式…

mysql查询2张表连接列名一样的情况

people表&#xff1a; person表&#xff1a; SELECT * FROM person LEFT JOIN people on people.idperson.id 查询的结果id(1)和name(1)说明列名重复 SELECT person.id,person.name,people.id as pid,people.name as pname FROM person LEFT JOIN people on people.idperso…