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

前言

处理做项目的问题,其中不乏奇奇怪怪的问题,其中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@Autowiredprivate 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());}//如果没有参数,使用-voidif (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.Userat 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.mzph.cn/news/609023.shtml

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

相关文章

Vue_00001_CLI

初始化脚手架 初始化脚手架步骤&#xff1a; 第一步&#xff08;仅第一次执行&#xff09;&#xff1a;全局安装vue/cli。 命令&#xff1a;npm install -g vue/cli 第二步&#xff1a;切换到要创建项目的目录&#xff0c;然后使用命令创建项目。 命令&#xff1a;vue creat…

python在一个文件夹中按文件名排序,获取这一文件的下一个文件名

在Python中&#xff0c;您可以使用sorted()函数对文件夹内的文件进行排序&#xff0c;并使用os模块来遍历这些文件。获取特定文件的下一个文件名可以通过排序后的列表来查找。下面是一个简单的示例代码&#xff0c;展示了如何对一个文件夹中的文件按文件名进行排序&#xff0c;…

【基础工具篇使用】Windows环境下瑞芯微开发工具的安装和使用

文章目录 Rockchip 烧录驱动的安装Rockchip 烧录工具使用导入配置MASKROM 模式烧录LOADER 模式烧录Update.img 包的烧录 Rockchip 烧录驱动的安装 瑞芯微提供了 RKDevTool 上位机烧录工具&#xff0c;此工具只能在 Windows 系统下运行&#xff0c;运行前要先安装驱动文件 Ro…

mitmproxy代理抓包使用mock数据

第一步 安装Python环境 下载Python环境安装包https://www.python.org/getit/https://link.jianshu.com/?thttps%3A%2F%2Fwww.python.org%2Fgetit%2F &#xff08;图a&#xff09; 安装Python的时候勾选“Add Python 3.5 to PATH”选项&#xff08;图a&#xff09; 打开CMD命…

Pytest接口自动化测试框架搭建

一. 背景 Pytest目前已经成为Python系自动化测试必学必备的一个框架&#xff0c;网上也有很多的文章讲述相关的知识。最近自己也抽时间梳理了一份pytest接口自动化测试框架&#xff0c;因此准备写文章记录一下&#xff0c;做到尽量简单通俗易懂&#xff0c;当然前提是基本的py…

书生·浦语大模型实战营第二次课堂笔记

文章目录 什么是大模型&#xff1f;pip&#xff0c;conda换源模型下载 什么是大模型&#xff1f; 人工智能领域中参数数量巨大、拥有庞大计算能力和参数规模的模型 特点及应用&#xff1a; 利用大量数据进行训练拥有数十亿甚至数千亿个参数模型在各种任务重展现出惊人的性能 …

数据结构入门到入土——链表(完)LinkedList

目录 一&#xff0c;双向链表 1.单向链表的缺点 2.什么是双向链表&#xff1f; 3.自主实现双向链表 接口实现&#xff1a; 二&#xff0c;LinkedList 1.LinkedList的使用 1.1 什么是LinkedList&#xff1f; 1.2 LinkedList的使用 1.LinkedList的构造 2.LinkedList的…

elementUI点击el-card选中变色,且点击别的空白处不变色

1. <script>的data中添加属性&#xff1a; selectIndex: 0 2.<template>中添加el-card元素&#xff1a; click.native调用原生click方法。 click.native是在vue中&#xff0c;避免vue父模块调用成了vue成子模块中的this.emit(click, value)的方法&#xff0c;而…

Pruning Papers

[ICML 2020] Rigging the Lottery: Making All Tickets Winners 整个训练过程中mask是动态的&#xff0c;有drop和grow两步&#xff0c;drop是根据权重绝对值的大小丢弃&#xff0c;grow是根据剩下激活的权重中梯度绝对值生长没有先prune再finetune/retrain的两阶段过程 Laye…

C++-nullptr-类型推导

1、nullptr&#xff08;掌握&#xff09;&#xff08;NULL 就是0&#xff09; NULL 在源码当中就是0&#xff0c;因此可能会存在一些二义性的问题。 #include <iostream> #include <memory> using namespace std;void func(int a) {cout << "a " …

[原创][R语言]股票分析实战[9]:周内第N天转换为星期N因子

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

工业异常检测AnomalyGPT-Demo试跑

写在前面&#xff1a;如果你有大的cpu和gpu可以使用&#xff0c;直接根据官方的安装说明就可以&#xff0c;如果没有&#xff0c;可以点进来试着看一下我个人的安装经验。 一、试跑环境 NVIDIA4090显卡24g,cpu内存33G&#xff0c;交换空间8g,操作系统ubuntu22.04(试跑过程cpu…

问题 F: 分巧克力

题目描述 儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有 N 块巧克力&#xff0c;其中第i 块HiWi 的方格组成的长方形。 为了公平起见&#xff0c;小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。 切出的巧克力需要满足&am…

SEO写作:撰写在Google上排名的博客文章的13个技巧

随着排名的提高&#xff0c;您的网站可以提高其整体知名度。最终目标是通过有效的优化来推动自然流量&#xff0c;增加转化率&#xff0c;并实现业务目标。 如果你不针对搜索引擎优化你的内容&#xff0c;你的网站可能会在搜索引擎结果页面&#xff08;SERP&#xff09;上出现…

第7章-第9节-Java中的Stream流(链式调用)

1、什么是Stream流 Lambda表达式&#xff0c;基于Lambda所带来的函数式编程&#xff0c;又引入了一个全新的Stream概念&#xff0c;用于解决集合类库既有的鼻端。 2、案例 假设现在有一个需求&#xff0c; 将list集合中姓张的元素过滤到一个新的集合中&#xff1b;然后将过滤…

Realm Management Extension领域管理扩展简介

本博客介绍了领域管理扩展(RME),这是Arm的架构扩展。RME是Arm机密计算架构(Arm CCA)的硬件组件,同时包括软件元素。RME动态地将资源和内存转移到新的受保护的地址空间,高特权软件或TrustZone固件无法访问。由于存在这个地址空间,Arm CCA构建了受保护的执行环境,称为领…

详解Oracle数据库的启动

Oracle数据库的启动&#xff0c;其概念可参考Overview of Instance and Database Startup。 其过程可参见下图&#xff1a; 当数据库从关闭状态进入打开数据库状态时&#xff0c;它会经历以下阶段。 阶段Mount状态描述1实例在没有挂载数据库的情况下启动实例已启动&#xff…

Numerical calculation and its application based on NumPy/SciPy

Numerical calculation and its application based on NumPy/SciPy 线性代表微分和积分统计插值 线性代表 { 3 x 1 2 x 2 8 − 3 x 1 5 x 2 − 1 \begin{cases} \begin{equation} \begin{split} 3x_12x_2 8\\ -3x_15x_2 -1 \end{split} \end{equation} \end{cases} {3x1​…

SpringBoot 注解超全详解

使用注解的优势&#xff1a; 采用纯java代码&#xff0c;不在需要配置繁杂的xml文件 在配置中也可享受面向对象带来的好处 类型安全对重构可以提供良好的支持 减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 1 注解详解&#xff08;配备了完善的释义&#xff0…

深入了解鸿鹄工程项目管理系统源码:功能清单与项目模块的深度解析

工程项目管理软件是现代项目管理中不可或缺的工具&#xff0c;它能够帮助项目团队更高效地组织和协调工作。本文将介绍一款功能强大的工程项目管理软件&#xff0c;该软件采用先进的Vue、Uniapp、Layui等技术框架&#xff0c;涵盖了项目策划决策、规划设计、施工建设到竣工交付…