mybatis plus相同Id与xml配置错误时,mybatis plus解决逻辑

news2024/11/24 6:43:54

前言

处理做项目的问题,其中不乏奇奇怪怪的问题,其中mybatis plus的问题感觉有点隐蔽,有些是运行时出现,有些是运行到具体的逻辑触发,对于应用的状态监控提出了极大的挑战,应用的状态由健康检查接口提供,或者TCP或者HTTP,那么健康检查要怎么写呢,比如K8S,一般使用HTTP GET方式要定时监控POD状态。

准备

准备SpringBoot与mybatis的demo,这个参考SpringBoot官网即可,数据库使用MySQL docker部署,毕竟docker部署方便:Basic Steps for MySQL Server Deployment with Docker

docker run --name mysql_8.0 -e MYSQL_ROOT_PASSWORD=123456i -d -i -p 3306:3306  container-registry.oracle.com/mysql/community-server:8.0

就可以使用client连接上去,然后建库表和demo数据,需要修改非本地登录mysql的能力

更新root登录限制开放

确认OK

造数据

mybatis plus的Id相同

依赖如下

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
    </dependencies>

dao与配置、main类

@SpringBootApplication
@MapperScan(basePackages = "com.feng.boot.mybatis.demo.dao")
public class MybatisMain {

    public static void main(String[] args) {
        SpringApplication.run(MybatisMain.class, args);
    }
}

@Mapper
public interface DemoDao {

    @Select("select * from user")
    List<User> selectUser();

    @Select("select * from user where name = #{name}")
    List<User> selectUser(String name);

}

@RestController
public class DemoController {

    @Lazy
    @Autowired
    private DemoDao demoDao;

    @RequestMapping("/user")
    public List<User> listUser(String name){
        return demoDao.selectUser(name);
    }

SpringBoot数据源配置自行处理,启动后日志

 _ _   |_  _ _|_. ___ _ |    _ 
| | |\/|_)(_| | |_\  |_)||_|_\ 
     /               |         
                        3.3.2 
2024-01-09 21:27:34.043 ERROR 3340 --- [           main] c.b.m.core.MybatisConfiguration          : mapper[com.feng.boot.mybatis.demo.dao.DemoDao.selectUser] is ignored, because it exists, maybe from xml file

但是 启动不会保错,如果是mybatis的starter则启动直接保错

让我们访问http://localhost:8080/user?name=demo

理论上只会有一条结果,然而:

 

2条,什么原因呢,开启trace日志

为啥不是我方法的执行结果,SQL都不对,这其实是mybatis plus留下的坑

 源码分析

启动过程就埋了坑,在

com.baomidou.mybatisplus.core.MybatisMapperAnnotationBuilder

通过generateResultMapName生成mybatis的Id时,mybatis plus做了定制

    private String generateResultMapName(Method method) {
        Results results = method.getAnnotation(Results.class);
        if (results != null && !results.id().isEmpty()) {
            return type.getName() + "." + results.id();
        }
        StringBuilder suffix = new StringBuilder();
        //参数拼接
        for (Class<?> c : method.getParameterTypes()) {
            suffix.append("-");
            suffix.append(c.getSimpleName());
        }
        //如果没有参数,使用-void
        if (suffix.length() < 1) {
            suffix.append("-void");
        }
        //类名+方法名+参数类型拼接
        return type.getName() + "." + method.getName() + suffix;
    }

所以对于mybatis plus,对于方法重载不存在id冲突的可能性,在

com.baomidou.mybatisplus.core.MybatisConfiguration

 所以出现启动时的error日志,然后直接return了,所以下面的第2条是没有载入mappedstatement

所以SQL永远是第1条,无论我们怎么调用

mybatis-starter

原生的mybatis-starter的org.apache.ibatis.builder.annotation.MapperAnnotationBuilder

实际上id也差不多,也是通过-void方式实现无参数id

 

但是在org.apache.ibatis.builder.MapperBuilderAssistant

会使用不带参数的Id来做校验,在org.apache.ibatis.session.Configuration

而不是像mybatis plus那样直接return了。

解决方法

无非是id冲突,只要安装方法名唯一的情况即可,不使用方法重载

结果OK

mybatis的xml配置错误的情况

如果使用xml配置,那么也会存在出现错误的情况

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.feng.boot.mybatis.demo.dao.DemoDao">
    <!--<select id="selectUser" parameterType="java.lang.String" resultType="com.feng.boot.mybatis.demo.entity.User">
        select * from user where name = #{name}
    </select>-->

    <select id="selectUser" parameterType="java.lang.String" resultMap="com.feng.boot.mybatis.demo.entity.User">
        select * from user where name = #{name}
    </select>

    <select id="selectUsers" resultType="com.feng.boot.mybatis.demo.entity.User">
        select * from user
    </select>

</mapper>

笔者故意写错selectUser的xml,但是笔者在调用

    @RequestMapping("/users")
    public List<User> listUser(){
        return demoDao.selectUsers();
    }

跟第1个xml毫无关系,但是调用报错

java.lang.IllegalArgumentException: Result Maps collection does not contain value for com.feng.boot.mybatis.demo.entity.User
	at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:1031) ~[mybatis-3.5.6.jar:3.5.6]

 其实这个都还好,关键是启动毫无错误,然而执行任意一条正确的SQL却报错了,莫非mybatis绝得还可以抢救一下。而且错误信息可以跟正确执行的逻辑毫无相关,如果启动后仅仅看启动日志,就会埋下极大隐患,需要健康检查覆盖mybatis才行。

源码分析

在mybatis的源码中,org.apache.ibatis.session.Configuration

mybatis的设计是,在任意statement执行前,执行未完成态的statement,执行快速失败,既然知道未完成,为什么启动不报错,也不任何日志提示呢

 根源来自org.apache.ibatis.builder.xml.XMLMapperBuilder

 xml解析失败,并不是报错,也没有日志,直接放在了未完成的statement,这里好歹给个日志啊,估计mybatis是准备支持抢救一下,不对,是支持statement在运行态注入一些数据实现完成态。

总结

mybatis plus这个是直接丢弃相同Id的statement,安装先后顺序,会造成执行过程的误解,不过有日志可以查看,而且mybatis原生的starter是有校验的,直接报错了。mybatis的xml如果写错,那么启动居然不报错,执行任意statement前需要执行未完成的statement,来达到快速失败的情况,这种情况对健康检查提出了新挑战,否则可能出现启动OK,但是mybatis失败的情况。

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

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

相关文章

VMware复制粘贴共享文件夹

win和虚拟机之间&#xff0c;无法复制粘贴&#xff0c;共享文件夹的解决方案。 安装VMware tools 1&#xff0c;先检查虚拟机设置部分。共享文件夹已启用。复制粘贴已启用。 2&#xff0c;安装tools.选择重新安装VMware tools. (此图片为安装过的截图) 成功后会显示如图。…

【Python书籍】字节大佬爆肝整理的Python背记手册最佳入门书籍,刷爆这本书你的Python就牛了!

前言&#xff1a; 现今有很多人都想学习Python&#xff0c;但是不乏有一些英语不好和非计算机专业的小伙伴&#xff0c;在最基础入门阶段会跟不上被甩在身后&#xff0c;就是在知识点的理解方面有所缺失&#xff0c;对于计算机的运算&#xff0c;计算机语言&#xff0c;计算机…

家政服务系统有哪些优势及特点

&#x1f308;家政系统小程序&#xff0c;有哪些功能优势&#xff01; 1、平台依托&#xff1a;&#x1f30d;小程序极速开发。 2、人员保障&#xff1a;顾客轻松注册&#xff0c;家政服务人员也有独立账号。 3、地域无忧&#xff1a;后台自定义开放城市范围。&#x1f31f; 4、…

MySQL决战:MySQL数据导入导出

目录 前言 一.navact数据导入导出&#xff08;第三方工具&#xff09; 1.导入数据 2.数据导出 二. mysqldump命令导入导出数据 1.mysqldump介绍 2.数据导出 3.数据导入 三.load data file进行数据导入导出&#xff08;只限于单表&#xff09; 1.数据导出 增加导出权…

SpringCloud系列篇:核心组件之网关组件

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.网关组件是什么 二. 网关组件的…

C++学习笔记——string类和new函数

目录 string类 1.功能增强 1.1 子字符串提取 1.2 字符串拼接 1.3 大小写转换 1.4 字符串比较 2.性能优化 3.使用示例 下面是一个简单的使用示例&#xff0c;展示了如何使用改进后的String类&#xff1a; NEW函数 2.1NEW函数的基本用法 2.2NEW函数的注意事项 2.3避…

大数据毕业设计:图书推荐系统+可视化+Django框架 图书管理系统 (附源码+论文)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

Vue3插件开发教程:步步指导如何编写Vue3插件

关注⬆️⬆️⬆️⬆️ 专栏后期更新更多前端内容 文章目录 Vue3 插件插件注册形式插件主要的场景使用插件Vue3 插件 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。 插件注册形式 一个插件可以是一个拥有 install() 方法的对象,也可以直接是一个安装函数本身。 i…

数 据 分 析 1

1.使用Wireshark查看并分析靶机桌面下的capture.pcapng数据包文件&#xff0c;找到黑客的IP地址&#xff0c;并将黑客的IP地址作为Flag值&#xff08;如&#xff1a;172.16.1.1&#xff09;提交&#xff1b;172.16.1.41 查找&#xff1a;tcp.connection.syn 2.继续分析captu…

SpringBoot 如何增强PageHelper入参的健壮性

PageHelper.startPage(int pageNum, int pageSize, boolean count) 参数为外部输入&#xff0c;故存在异常输入场景。比如 pageNum 和 pageSize 输入的值 负数 或者 0&#xff0c;所以引入PageUtils来对入参进行判断矫正&#xff0c;从而避免引入异常。 第1步&#xff1a;支持…

Windows无线网络分析报告

概述信息 客户现场有一套大屏展示系统&#xff0c;它是通过戴尔小主机、无线网络、电视机的方式来工作。大屏展示的内容非常实时&#xff0c;对于内容的刷新也比较高。客户反馈最近经常会出现网络抖动的情况&#xff0c;但远程检查又无法发现问题点。 此时&#xff0c;Window…

mysql基础-常用函数汇总

目录 1. 查询技巧 2. 时间函数 2.1 now() 2.2 current_date() 2.3 时间差timestampdiff&#xff08;&#xff09;与datediff&#xff08;&#xff09; 2.4 其他时间函数 3. 字符函数 3.1 截取函数 3.2 分割函数 3.3 left与right函数 3.4 其他函数 4. 数字函数 5. …

Python进阶之元类

Python进阶之元类 目录 什么是元类&#xff1f; 元类的调用流程 根据类自定义元类 __new__方法以及参数 ----------cls ----------name ----------bases ----------attrs __call__方法 生成对象的完整代码 什么是元类&#xff1f; 在python面向对象中&#xff0c;我们知道所有…

Redis:原理速成+项目实战——Redis实战5(互斥锁、逻辑过期解决缓存击穿问题)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis实战4&#xff08;解决Redis缓存穿透、雪崩、击穿&#xff09; &#x1f4da;订阅专…

web左侧伸缩菜单栏/导航栏

效果展示&#xff1a; 百度网盘链接下载全部资源&#xff1a; http://链接&#xff1a;https://pan.baidu.com/s/1ZnKdWxTH49JhqZ7Xd-cJIA?pwd4332 提取码&#xff1a;4332 html/JQuery代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head&g…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷②

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷2 目录 需要竞赛软件包环境以及备赛资源可私信博主&#xff01;&#xff01;&#xff01; 2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷2 模块一 …

Spring MVC自定义类型转换器!!!

使用场景 在index.jsp里面添加日期类型 <form action"account/saveAccount" method"post">账户名称&#xff1a;<input type"text" name"name"><br/>账户金额&#xff1a;<input type"text" name&quo…

TCP的这些特性你知道吗?(滑动窗口篇)

如果每次 [发送方] 需要等待接受方返回数据才能发送下一条数据&#xff0c;会导致网络通信的效率非常的低&#xff0c;于是在TCP中 引入了窗口这个概念&#xff0c;即使在往返时间较长的情况下&#xff0c;它也不会降低网络通信的效率。有了窗口&#xff0c;并不代表可以无限 接…

windows rtmp发送数据流程抓包

一、connect 返回Window Acknowledgement Size&#xff1a; 返回Set Peer Bandwidth 二、 releaseStream 三、 FCPublish 四、 createStream 五、 _checkbw 六、 FCPublish返回 七、createStream 八、 _checkbw返回 九、发送关键帧 十、发送视频帧 十一、FCUnpublish 十二、del…

【Verilog】运算符

系列文章 数值&#xff08;整数&#xff0c;实数&#xff0c;字符串&#xff09;与数据类型&#xff08;wire、reg、mem、parameter&#xff09; 系列文章算术运算符关系运算符相等关系运算符逻辑运算符按位运算符归约运算符移位运算符条件运算符连接和复制运算符 算术运算符 …