【Mybatis出现bug】应为 <statement> 或 DELIMITER,得到 ‘id‘

目录

问题出现情景

问题出现原因

具体解决思路

阶段一------鸵鸟逃避法

阶段二------模仿前人,语言注入修改

阶段三------知根知底,彻底解决

最终解决方案

最后


本文重在记录个人修改bug的全过程与整体思路,极具私人性和记录性质。如若只想知道如何解决问题可直接跳转至阶段三的最终解决方案。

问题出现情景

使用MybatisX-Generator自动补全基础代码时生成的.xml文件出现爆红。

错误信息为"应为 <statement> 或 DELIMITER,得到 'id'"

经过几番折腾才解决这个问题,因此这里啰里啰唆的记录一下解决问题的全阶段。

问题出现原因

本质是IDEA自己抽风,语法检测出现异常,本不必理会但红闪闪的报错实在碍眼。

具体原因:用来检测语法的内置的检查手册(官方写死的规则),它的工作是:识别.xml 文件里的 Mybatis 标签(比如<select>、<insert>、<sql>),并把这些标签里的内容当成 SQL 语句来检查语法。 但这份 "内置手册" 有个 bug:它只认<statement>这种标签,却不认识 Mybatis 里的<sql>标签(<sql>是 Mybatis 用来复用 SQL 片段的标签,比如定义一个通用的查询字段),当它看到<sql id="xxx">里的 "id" 属性时,就懵了,直接报错 "应该是<statement>"。

具体解决思路

阶段一------鸵鸟逃避法

最开始我写项目用不到xml,所以直接眼不见心不烦,把整个sql标签删的干干净净了。

失效原因:

后面继续使用MybatisX-Generator自动补全基础代码,自己实在看不下去了

阶段二------模仿前人,语言注入修改

在之后开始上网找解决方案。然而我的语言注入模块没有`xml:iBatis3`相关的配置项。

因此我找了个长得像的,把这里的"sql|"删掉。居然奇迹般的不报错了。

失效原因:

重启IDE后又开始爆红。

阶段三------知根知底,彻底解决

最后实在受不了了,于是开始截图询问ai,经过一段时间的交流终于对这个bug知根知底,开始着手解决。

这里完整的逻辑是:IDEA通过"语言注入"模块的配置检查语法错误,怎么检查呢,通过这里的命名空间设置来检查本地名称。

  • 命名空间是 "范围过滤器" 它先锁定规则生效的 XML 文件范围。比如你填了 MyBatis 3 的官方命名空间 http://mybatis.org/dtd/mybatis-3-mapper.dtd,IDEA 就知道这个规则只对所有 MyBatis 3 的 Mapper XML 文件生效,不会影响其他类型的 XML(比如 Spring 配置文件)。

  • 本地名称是 "标签精准定位器" 在确定了命名空间的范围后,IDEA 再用 "本地名称" 去匹配这个范围内的具体标签。比如你设置的 select|insert|update|delete,就是告诉 IDEA:"只对这些标签里的内容做 SQL 处理"。

而之前的问题就是因为旧规则的「本地名称」包含了 sql

  • 命名空间是对的(MyBatis 3 官方地址)
  • 本地名称里的 sql 让 IDEA 错误地把 <sql> 标签(用来定义 SQL 片段的标签)也当成了要检查的 SQL 语句
  • <sql> 标签里的 id 属性并不是 SQL 语法,所以就触发了 "应为 <statement> 或 DELIMITER,得到 'id'" 的报错

为什么在阶段二重启IDEA修改会失效呢:

IDEA 的 "Built-in(内置)"( 与IDE自己创建的自定义模板对应**) 语言注入规则是只读的**。

你手动修改 "本地名称" 后,IDEA 不会保存这个更改,所以重启后会自动恢复到默认值,导致问题重现。

"把sql删掉就好" 只是临时生效,因为修改的是内置规则,而不是创建一个优先级更高的自定义规则。

为什么我的设置中没有前人的`xml:iBatis3`相关的配置项:这个配置项名字就是随便起的,没有也正常。这并不设计系统的根本底层逻辑。

最终解决方案

禁用内置规则(为什么要做?)

  • 内置手册有 bug,留着它会和你新做的手册冲突,所以先把内置的 "Mybatis SQL 检查规则" 关掉,避免 "检查员" 同时看两份矛盾的手册。

2. 创建自定义规则(为什么要做?)

  • 你自己做一份新手册,明确告诉 IDEA:只检查<select>、<insert>、<update>这些真正执行 SQL 的标签,不要管<sql>标签(因为<sql>只是复用片段,不是执行语句)。
  • 这份自定义手册是「可保存的」,IDEA 不会因为重启就删掉,所以规则能永久生效。

3. 修复 XML 的 DOCTYPE 声明(为什么要做?)

  • 相当于给你的.xml 文件加个 "身份标识",告诉 IDEA:"这是 Mybatis 3 的文件,按 Mybatis 的规则来,不是普通 XML",避免 IDEA 用错检查规则。

4. 重启验证(为什么要做?)

  • 让 IDEA 加载你新做的自定义手册,确认手册能正常生效,不会被内置规则覆盖
  • 打开 IDEA → 顶部菜单找「File」→「Settings」→ 搜索「Language Injection」(语言注入);
  • 找到所有 "Built-in(内置)" 的、和 "MyBatis sql" 相关的规则,把勾选去掉(禁用内置 bug 规则);
  • 点击左上角「+」号,新增一个规则:
    • 名称随便填(比如 Mybatis 规则);
    • 语言选「SQL」;
    • 本地名称填「select|insert|update|delete」(只检查这些标签,不包含 sql);
    • 命名空间填「http://mybatis.org/dtd/mybatis-3-mapper.dtd」(Mybatis 的官方标识);
  • 保存规则,重启 IDEA → 你的.xml 文件就不会再爆红了。

最后

最后我尝试顺应IDEA的检查语法逻辑进行修改,也就是直接修改语法,结果都不行。

原因:

IDEA 对 MyBatis XML 的检查是分层的,改的只是内容,没动到根因:

  1. DELIMITER 还是报错 IDEA 的内置规则是先检查 <sql> 标签的属性 (比如 id="BaseColumnList"),再看内容。它看到 id 属性就直接触发了 "应为 <statement> 或 DELIMITER" 的报错,根本没往下看你内容里写的 DELIMITER

  2. SELECT 报 "无法解析列" 这是因为 IDEA 把 <sql> 标签内容当成了完整的 SQL 语句,但它不知道这些列属于哪个表,所以 SQL 检查器就报错说 "找不到列"。

  3. <statement> 报 "不允许使用元素" MyBatis 3 的官方 DTD(mybatis-3-mapper.dtd)里已经彻底移除了 <statement> 标签(这是 MyBatis 1.x 的旧标签),所以 IDEA 的 XML 结构验证器直接就会报错。

阶段三标题所谓的知根知底明显是戏言了,这里也只是根据笨蛋ai的意见进行尝试。恐怕文章里还存在许多我不清楚的问题纰漏。欢迎读者在评论区补充勘误。

相关推荐
小北方城市网2 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
六义义3 小时前
java基础十二
java·数据结构·算法
毕设源码-钟学长3 小时前
【开题答辩全过程】以 基于SpringBoot的智能书城推荐系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
笨手笨脚の4 小时前
深入理解 Java 虚拟机-03 垃圾收集
java·jvm·垃圾回收·标记清除·标记复制·标记整理
cyforkk4 小时前
MyBatis Plus 字段自动填充:生产级实现方案与原理分析
mybatis
莫问前路漫漫4 小时前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
九皇叔叔4 小时前
【03】SpringBoot3 MybatisPlus BaseMapper 源码分析
java·开发语言·mybatis·mybatis plus
挖矿大亨4 小时前
c++中的函数模版
java·c++·算法
a程序小傲5 小时前
得物Java面试被问:RocketMQ的消息轨迹追踪实现
java·linux·spring·面试·职场和发展·rocketmq·java-rocketmq
青春男大5 小时前
Redis和RedisTemplate快速上手
java·数据库·redis·后端·spring·缓存