当前使用版本

3.5.2

该问题是如何引起的?

无法保证XML中的Sql、注解的Sql和标准CrudSql到底那个有效。

在com.baomidou.mybatisplus.core.MybatisMapperAnnotationBuilder#parse的注释中说 MybatisPlus 加载 SQL 顺序: 1、加载 XML中的 SQL 2、加载 SqlProvider 中的 SQL 3、XmlSql 与 SqlProvider不能包含相同的 SQL 调整后的 SQL优先级:XmlSql > sqlProvider > CurdSql

但是,具体实现无法保证该顺序,解析代码看com.baomidou.mybatisplus.core.MybatisMapperAnnotationBuilder#parse ```public void parse() { String resource = type.toString(); if (!configuration.isResourceLoaded(resource)) { loadXmlResource();//===>1,解析XmlSql ... for (Method method : type.getMethods()) {//===>2,解析sqlProvider .... } // TODO 注入 CURD 动态 SQL , 放在在最后, because 可能会有人会用注解重写sql try { // https://github.com/baomidou/mybatis-plus/issues/3038 if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) { parserInjector();//===>3, 注入通用 CurdSql } } catch (IncompleteElementException e) { configuration.addIncompleteMethod(new InjectorResolver(this)); } } parsePendingMethods();//===>4,每完成一个mapper(包括xml)的解析后,去尝试解析待定的 }


在1处解析XmlSql时,遇到问题,则把该方法放入待定列表。
org.apache.ibatis.builder.xml.XMLMapperBuilder#buildStatementFromContext

private void buildStatementFromContext(List list, String requiredDatabaseId) { for (XNode context : list) { ... try { statementParser.parseStatementNode(); } catch (IncompleteElementException e) { configuration.addIncompleteStatement(statementParser);//放入待定列表 } } } ``` 在注入标准Crud时,遇到问题也会加入待定列表。

如果按照这样的逻辑,假如XML文件、注解和方法注入包括了相同id的方法,最后到底那个生效,完全不确定。

建议改变思路,重构代码,在加入MapStatement时,如果在待定列表中有相同id存在,则为每个id建立一个待定队列,并把它放在该id后面排队,当所有的xml文件,注解都解析完了,再去解析待定列表,最后确实无法完成,就选择后面排队的。

这样的好处是,XmlSql 、SqlProvider以及CurdSql能够得到有效保证。也就能够确定的用xml覆盖注解、注解覆盖标准CRUDSql。

Comment From: miemieYaho

欢迎pr