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
    @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失败的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

facebook广告的基础知识与类型

Facebook广告是在Facebook平台上展示的一种数字广告形式&#xff0c;它允许广告主通过定位特定的受众群体来推广他们的产品、服务或品牌。以下是一些关于Facebook广告的基础知识&#xff1a; 支持Facebook广告的卡、556150、532959&#xff0c;点击获取 广告形式&#xff1a; …

【Proteus仿真】【Arduino单片机】智能感应温控风扇

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶显示模块、DS18B20温度、按键、声光报警、L293D电机驱动等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示传感器检…

.NET Framework 与 .NET Core 与 .NET Standard 之间的差异

介绍 在本文中&#xff0c;我们将探讨 .NET Framework、.NET Core 和 .NET Standard 之间的差异。 .NET Framework 与 .NET Core .NET框架.NET核心 历史 .NET Framework 是 .NET 的第一个实现。 .NET Core 是 .NET 的最新实现。 开源 .NET Framework 的某些组件是开源的。 .N…

前端实现搜索功能

最近遇到一个需求,用户在输入框输入关键字之后,点击搜索按钮后进行搜索,如下图,选中的数据在下面,上面展现的是搜索后的数据,现在选中了2条数据: 当用户输入KET后点击搜索,搜出的结果有16条,勾选全选选中后,将选中的16条的数据加到之前已选的2条数据里,于是此时已选…

认识Linux指令之 “ head tail ” 命令

01.head指令 head 与 tail 就像它的名字一样的浅显易懂&#xff0c;它是用来显示开头或结尾某个数量的文字区块&#xff0c;head 用来显示档案的开头至标准输出中&#xff0c;而 tail 想当然尔就是看档案的结尾。 语法&#xff1a; head [参数]... [文件]... 功能&#…

SAP CO11N报工批次分割(拆分)

CO11N做报工的时候&#xff0c;下阶料启用了批次&#xff0c;比如需要过账4166个&#xff0c;但是每一批次的库存都不满足4166个&#xff0c;所以需要拆分&#xff08;分割&#xff09;处理 这个时候我们就需要对这一行做分割处理 选中这一行&#xff0c;点击‘分割’按钮 弹…

Speech | 语音克隆Openvoice的论文解读及项目实现

本文主要介绍了语音克隆Openvoice的论文以及项目实现~ 论文题目&#xff1a;OpenVoice: Versatile Instant Voice Cloning 论文地址&#xff1a;2312.01479.pdf (arxiv.org) 项目地址&#xff1a;https://github.com/myshell-ai/OpenVoice.git 官网&#xff1a;Home (myshell.a…

C 练习实例23

题目&#xff1a;打印出如下图案&#xff08;菱形&#xff09;。 * *** ***** ******* ***** *** * 题目分析&#xff1a; 先打印前4行&#xff0c;因为是递增关系。 第0行&#xff1a;打印3个空格&#xff0c;1个* 第1行&#xff1a;打印2个空格&#xff0c;3个*…

【Github-Action】GithubAction 环境下,如何将临时生成的文件推送至指定分支。

通过这篇文章你可以掌握如何将github action 环境下临时生成的文件推送至指定分支&#xff0c;并且可以打开利用github开放的api做各种强大或有趣的事情的视野和思路。 如果你对github-action感兴趣&#xff0c;还可以看这篇文章&#xff0c; 这篇文章教会你如何开发Github Act…

分布式系统架构设计之分布式消息队列中间件的技术选型报告

1、主流消息队列中间件 01 Kafka 基本原理 Kafka 基于发布-订阅模式&#xff0c;它维护了一个或多个 Topic&#xff0c;生产者将消息发送到 Topic&#xff0c;消费者从 Topic 中读取消息。Kafka 强调高吞吐量&#xff0c;通过批量处理、顺序 I/O 和零拷贝等技术实现高性能 …

微信扫码进入小程序特定页面

小程序配置 开发 - 开发管理 - 开发设置-普通链接二维码打开小程序 配置好的截图 如下&#xff1a;二维码规则建议是自己的域名 /mini/ 功能页面 pages/index/index 是为了方便跳转其他页面 记得把校验文件发给后端 web 端处理 二维码格式为&#xff1a;二维码规则/功能页…

基于 SpringBoot + magic-api + Vue3 + Element Plus + amis3.0 快速开发管理系统

Tansci-Boot 基于 SpringBoot2 magic-api Vue3 Element Plus amis3.0 快速开发管理系统 Tansci-Boot 是一个前后端分离后台管理系统&#xff0c; 前端集成 amis 低代码前端框架&#xff0c;后端集成 magic-api 的接口快速开发框架。包含基础权限、安全认证、以及常用的一…

2024美赛数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

【深度学习:数据增强】计算机视觉中数据增强的完整指南

【深度学习&#xff1a;数据增强】计算机视觉中数据增强的完整指南 为什么要做数据增强&#xff1f;等等&#xff0c;什么是数据增强&#xff1f;数据增强技术数据增强的注意事项和潜在陷阱什么时候应该做数据增强&#xff1f;类不平衡的数据增强那么我应该选择哪些转换呢&…

【Wordpress高级教程】 Wordpress免插件建立站群,wordpress整站迁移/安装

提示&#xff1a;该方法适用于Wordpress的站点&#xff0c;且无需插件哦&#xff08;插件一般都需要付费的&#xff0c;博主比较穷&#xff0c;我们就通过技术来解决&#xff09; 文章目录 前言一、准备工作二、搭建站群1.打包wp-content2.导入新站点3.导出数据库4.修改数据库配…

redis的高可用(主从复制、哨兵、群集)

redis的高可用&#xff08;主从复制、哨兵、群集&#xff09; 主从复制&#xff1a;主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份&#xff0c;以及对于读操作的负载均衡和简单的故障恢复。缺陷&…

[Docker] Mac M1系列芯片上完美运行Docker

docker pull qinchz/dm8-arm64 container_name: dm8ports:- "5236:5236"mem_limit: 1gmemswap_limit: 1gvolumes:- /data/dm8:/home/dmdba/data 数据库实例参数已修改&#xff0c;接近oracle使用习惯 #字符集 utf-8 CHARSET1 #VARCHAR 类型对象的长度以字符为单位 …

vmware虚拟机内存异常占用问题一例

关键词 vmware esxi、hypervisor虚拟化平台内存模式 Guest virtual memory 一、问题现象 业务一台vmware虚拟机出现内存使用率告警&#xff0c;运维人员登录系统检查内存确实高水位状态 检查各进程使用内存不高&#xff0c;合计内存总数与使用率占用情况明显不匹配&#xf…

将dumpbin从Visual Studio中抠出来,并使用dumpbin查看exe和dll库的依赖关系

目录 1、初步说明 2、在开发的机器上使用dumpbin工具查看dll库的依赖关系 3、将dumpbin.exe从Visual Studio中抠出来 3.1、找到dumpbin.exe文件及其依赖的dll文件 3.2、在cmd中运行dumpbin&#xff0c;提示找不到link.exe文件 3.3、再次运行dumpbin.exe提示找不到mspdb10…

UV胶水能够粘接聚苯乙烯PS吗?需要注意哪些事项?又有哪些优势呢?

聚苯乙烯&#xff08;Polystyrene&#xff0c;简称PS&#xff09;是一种常见的合成聚合物&#xff0c;属于热塑性塑料。它是由苯乙烯单体聚合而成的&#xff0c;具有轻质、透明或半透明、电绝缘性好等特点。常见: 包装材料白色泡沫塑料&#xff08;EPS&#xff0c;用于包装、保…