目录
本文重在记录个人修改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 的检查是分层的,改的只是内容,没动到根因:
-
加
DELIMITER还是报错 IDEA 的内置规则是先检查<sql>标签的属性 (比如id="BaseColumnList"),再看内容。它看到id属性就直接触发了 "应为<statement>或 DELIMITER" 的报错,根本没往下看你内容里写的DELIMITER。 -
加
SELECT报 "无法解析列" 这是因为 IDEA 把<sql>标签内容当成了完整的 SQL 语句,但它不知道这些列属于哪个表,所以 SQL 检查器就报错说 "找不到列"。 -
加
<statement>报 "不允许使用元素" MyBatis 3 的官方 DTD(mybatis-3-mapper.dtd)里已经彻底移除了<statement>标签(这是 MyBatis 1.x 的旧标签),所以 IDEA 的 XML 结构验证器直接就会报错。
阶段三标题所谓的知根知底明显是戏言了,这里也只是根据笨蛋ai的意见进行尝试。恐怕文章里还存在许多我不清楚的问题纰漏。欢迎读者在评论区补充勘误。