本地运行好好的 Java 程序, 一发布到线上就报错的灵异事件终于让我碰到了

news2025/1/12 10:40:52

说明

本文涉及的相关软件版本如下:

  • mybatis 3.4.x
  • HotSpot JDK1.8
  • Windows 11
  • IDEA 2022.3

先看一段 mybatis 相关的代码

今天一个朋友丢给我如下一段代码: 然后跟我讲为什么本地是好好的, 发布到线上执行就报错。

  • BlogMapper.java
public interface BlogMapper {
    List<Blog> select(Integer id, String title);
}
  • BlogMapper.xml
<select id="select">
    select * from my_blog
    <where>
      <if test="id!=null">
        id = #{id}
      </if>
      <if test="title!=null">
        and title = #{title}
      </if>
    </where>
</select>
  • 报错信息

报错信息也很容易理解: mybatis 动态生成 sql 时,提示参数 id 找不到, 只找到了 [arg1, arg0, param1, param2] 这四个可用的参数名称

Caused by: org.apache.ibatis.binding.BindingException:

Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]

mybatis 官方说明

mybatis 官网文档说明如下:

如果你的映射方法接受多个参数,就可以使用这个注解自定义每个参数的名字。否则在默认情况下,除 RowBounds 以外的参数会以 “param” 加参数位置被命名。例如 #{param1}, #{param2}。如果使用了 @Param("person"),参数就会被命名为 #{person}

因此我们上面的使用方式明显是不对的, 理论上讲这段程序不管在 线上 还是 本地编辑器 运行, 都是会提示同样的报错的。

mybatis 源码分析

关于 mybatis 是如何把 mapper.java参数名 绑定到 mapper.xml占位符 上的, 可以直接看 ParamNameResolver.java 这个类

源码中重点内容已经 标识 出来, 我们只需要关注 重点1重点2

其实源码注释说得很明白了:

  • 如果使用了 @Param("名称") 注解, 就用注解中的名称;
  • 否则, 就调用 isUseActualParamName() 方法;
  • 如果还是拿不到, 就由 mybatis 生成。
public static final boolean parameterExists;

  static {
    boolean available = false;
    try {
      Resources.classForName("java.lang.reflect.Parameter");
      available = true;
    } catch (ClassNotFoundException e) {
      // ignore
    }
    parameterExists = available;
  }

// java.lang.reflect.Parameter
private String getActualParamName(Method method, int paramIndex) {
    if (Jdk.parameterExists) {
      return ParamNameUtil.getParamNames(method).get(paramIndex);
    }
    return null;
}

从上面的源码可以看出, 只要程序能够加载到 java.lang.reflect.Parameter 这个类, 我们就能拿到参数名称。

/**
 * Information about method parameters.
 *
 * A {@code Parameter} provides information about method parameters,
 * including its name and modifiers.  It also provides an alternate
 * means of obtaining attributes for the parameter.
 *
 * @since 1.8
 */
public final class Parameter implements AnnotatedElement {
    
}

从这个类的注释可以看出, 这个类是 JDK1.8 才引入的类, 也就是说我们是可以拿到真实参数名称的。 那么为什么还是报错呢?

打断点调试

通过断点调试, 我们可以看到我们拿到的参数名称是 arg0arg1, 并不是我们期望的 idtitle

这两个名称在我们前面报错信息的可选值范围内,那么 param0param1 是如何生成的呢?
在这里插入图片描述

param0param1mybatis 为我们生成的, 用来兜底的, 那么 arg0arg1 是怎么生成的呢 ?

Java 编译

通过《深入理解 Java 虚拟机》 一说, 我们可以知道, 字段名是放在 class 文件, 而 class 文件是在编译期生成的。编译的命令是 javac 那么我们可以尝试查看 javac 命令是否为我们提供了相关参数来帮我们获取参数名称。

我们在命令行工具上执行 javac 命令, 控制台会显示它的所有 可选参数, 其中有一个参数的说明如下:

-parameters 生成元数据以用于方法参数的反射

意思就是 编译程序 时, 如果加上这个参数, 在程序运行过程中,就可以拿到程序中方法中的 参数名称.

那么我们 IDEA 编译如何加上这个参数呢?

在这里插入图片描述
除此之外, 我们还可以通过 IDEA 提供的 jclasslib 插件帮我们翻译 class 文件:

在这里插入图片描述

从上图可以看出, 当我们加上编译参数时, class 文件中多了一个描述符. 也就是我们方法参数的元数据信息.

找到真凶

原来我朋友之前在使用 IDEA 时, 如果遇到了一些问题(忘记了具体什么问题), 然后稀里糊涂就加了上述配置, 后来也一直没删除,最后今天就碰巧遇上了文中所描述的 “灵异事件”。

根据官方资料再次强化我们的结论

详情请参考 Access to Parameter Names at Runtime

我摘抄了其中一段话:

The proposed approach is to create an optional new JVM attribute in version 52.0 class files to store information about the parameters of a JVM-level method

大致意思是在 JDK8 版本中, 可以 选择性class 文件存储 方法的参数名称.

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

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

相关文章

【python机器学习】K-Means算法详解及给坐标点聚类实战(附源码和数据集 超详细)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 人们在面对大量未知事物时&#xff0c;往往会采取分而治之的策略&#xff0c;即先将事物按照相似性分成多个组&#xff0c;然后按组对事物进行处理。机器学习里的聚类就是用来完成对事物进行分组的任务 一、样本处理 聚类…

技术原理|Hologres Binlog技术原理揭秘

作者&#xff1a;张高迪&#xff08;花名杳天&#xff09;&#xff0c;Hologres研发。 同传统MySQL数据库&#xff0c;Hologres支持Hologres binlog&#xff0c;记录数据库中所有数据的变化事件日志。通过Hologres binlog&#xff0c;可以非常方便灵活的实现数据之间的复制、同…

“电池黑马”瑞浦兰钧增速惊人,动储双起飞

撰稿 | 多客 来源 | 贝多财经 12月14日&#xff0c;“电池黑马”瑞浦兰钧能源股份有限公司&#xff08;以下简称“瑞浦兰钧”&#xff09;向港交所主板提交上市申请&#xff0c;摩根士丹利和中信证券为其联席保荐人。至此&#xff0c;国内动力电池装机量排名前十的企业均已上…

DB Optimizer Multiplatform SQL评测和调优IDE

DB Optimizer Multiplatform SQL评测和调优IDE 增加了对最新版本Log4j的支持。 改进了分析会话功能&#xff0c;可提前提醒用户可能有问题的SQL。 DB Optimizer可以快速发现、诊断和优化性能较差的SQL。DBOptimizer使DBA和开发人员能够在整个开发生命周期中优化SQL性能&#xf…

合并多个有序数组

合并多个有序数组题目描述思想代码实现变形题目题目描述 我们现在有多个已经有序的数组&#xff0c;我们知道每个有序数组的元素个数和总共的有序数组的个数&#xff0c;现在请设计一个算法来实现这多个有序数组的合并&#xff08;合并成一个数组&#xff09;; 例如&#xff1a…

Chrome浏览器可以用ChatGPT了?

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store 最近这段时间想必 和我一样&#xff0c;都被chatGPT刷屏了。 在看到网上给出的一系列chatGPT回答问题的例子和自己亲自体验之后&#xff0c;的确发现它效果非常令人惊艳。 chatGPT的火热程度在开源社…

turbo编码原理

一、原理 Turbo的编码器由两个并行的分量编码器组成。分量编码器的选择一般是卷积码。在Turbo码中&#xff0c;输入序列在进入第二个编码器时须经过一个交织器 &#xff0c;用于将序列打乱。两个编码器的输出共同作为冗余信息添加到信息序列之后&#xff0c;对抗信道引起的错误…

实战SupersetBI报表之数据集图表配置

上集已经安装完Superset -实战SupersetBI报表之安装 本集开始讲解 根据数据集配置图表&#xff1a;以简单的员工花名册 为例 1、首先配置数据库 上次安装的时候也提到过 如果服务之间都是docker 安装。必须保证能够通信 下面根据实际参数配置即可 当我们配置好数据库之后 就可以…

如何保证TCP传输的可靠性

重传机制&#xff0c;流量控制&#xff0c;拥塞控制 1.重传机制&#xff1a; 序列号确认应答 当发送端的数据到达接收主机的时候&#xff0c;接收端主机会返回一个确认应答消息&#xff0c;表示已经收到消息 当数据发生丢包时&#xff0c;用重传机制解决 重传机制有好几种…

【Anime.js】——用Anime.js实现动画效果

目录 目标&#xff1a; ​编辑1、确定思路 2、创建网格 3、设置随机位置 4、创建时间轴动画 完整代码&#xff1a; 目标&#xff1a; 实现自动选点&#xff0c;对该点进行先缩小后放大如何回到比其他点大一点的状态&#xff0c;并以该点从外向内放大 1、确定思路 2、创建网…

第12届嵌入式蓝桥杯真题-停车场管理系统的设计与实现

目录 实验要求&#xff1a; 实验思路&#xff1a; 核心代码&#xff1a; &#xff08;1&#xff09;主函数 &#xff08;2&#xff09;lcd显示 &#xff08;3&#xff09;按键函数 &#xff08;4&#xff09;LED显示函数 &#xff08;5&#xff09;业务处理函数 &…

深度理解取模

深度理解取模一.取模概念二.负数取模三.进一步的解释四.取模和取余是一样的吗&#xff1f;一.取模概念 二.负数取模 上面的代码一目了然就不再多少啦&#xff0c;但如果是负数取模又该怎么办呢&#xff1f; 以上a/b-3是很好理解的&#xff0c;那为什么取模后的值是-1呢&#xf…

useEffect 和 useLayoutEffect 的源码解读

文章目录useEffect 和 useLayoutEffect 的源码解读useEffect源码解读mountEffectImplpushEffectupdateEffectImpl疑惑&#xff1a;useLayOutEffect源码解读mountLayoutEffectupdateLayoutEffect总结useEffect 和 useLayoutEffect 的源码解读 useEffect 文件在 packages/react…

毕业设计-基于深度学习的交通标识识别-opencv

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

叠氮-聚乙二醇-羧基,N3-PEG-COOH 异双功能PEG衍生物COOH-PEG-N3又名Azide-PEG-acid,可用于修饰蛋白质

英文名称&#xff1a;N3-PEG-COOH&#xff1b;COOH-PEG-N3 Azide-PEG-acid 中文名称&#xff1a;叠氮-聚乙二醇-羧基&#xff1b;羧基-聚乙二醇-叠氮 存储条件&#xff1a;-20C&#xff0c;避光干燥 用 途&#xff1a;仅用于科学研究&#xff0c;不能用于人体 外观: 固体或…

【OpenFeign】【源码+图解】【一】HelloWorld及其工作原理

目录1. HelloWorld1.1 pom.xml1.2 yml配置1.3 开启OpenFeign1.4 创建Product的FeignClient1.5 Controller2. OpenFeign的工作原理1. HelloWorld 服务中心以及Product微服务继续使用LoadBalance中的HelloWorld&#xff0c;新建一个client作为OpenFeign的例子 1.1 pom.xml 引入…

【视觉高级篇】26 # 如何绘制带宽度的曲线?

说明 【跟月影学可视化】学习笔记。 如何用 Canvas2D 绘制带宽度的曲线&#xff1f; Canvas2D 提供了相应的 API&#xff0c;能够绘制出不同宽度、具有特定连线方式&#xff08;lineJoin&#xff09;和线帽形状&#xff08;lineCap&#xff09;的曲线&#xff0c;绘制曲线非…

力扣(1053.115)补9.13

1053.不相交的线 不会&#xff0c;这题和1143题代码一样&#xff0c;只不过题意不太能懂&#xff0c;难想&#xff0c;难想。 115.不同的子序列 难想&#xff0c;这种题就跟该画dp图去理解&#xff0c;太难了。 跟着图去模拟一下&#xff0c;要不然真的答案都看不懂。 dp[i][j…

Servlet知识

1、什么是Servlet&#xff1f; Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;用Java编写的服务器端程序&#xff0c;具有独立于平台和协议的特性&#xff0c;主要功能在于交互式地浏览和生成数据&…

机器学习笔记:scikit-learn pipeline使用示例

0. 前言 在机器学习中&#xff0c;管道机制是指将一系列处理步骤串连起来自动地一个接一个地运行的机制。Scikit-Learn提供了pipeline类用于实现机器学习管道&#xff0c;使用起来十分方便。 既然要将不同处理步骤串联起来&#xff0c;首先必须确保每个步骤的输出与下一个步骤的…