Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

当Mapper类中有重载方法的时候用jrebel启动报错,而禁用本插件之后用jrebel启动则正常 #24

Open
jiangjihui opened this issue Feb 20, 2022 · 9 comments
Assignees

Comments

@jiangjihui
Copy link

jiangjihui commented Feb 20, 2022

示例代码:

@Mapper
public interface ExamManageMapper {
    @Select("select * from exam_manage")
    List<ExamManage> findAll();

    @Select("select * from exam_manage")
    IPage<ExamManage> findAll(Page page);
}

报错内容:

Mapped Statements collection already contains value for com.exam.mapper.ExamManageMapper.findAll.
 please check com/exam/mapper/ExamManageMapper.java (best guess) and com/exam/mapper/ExamManageMapper.java (best guess)

image

@SweetInk SweetInk added the bug Something isn't working label Feb 20, 2022
@SweetInk
Copy link
Owner

明天验证下,不知道mybatis会不会也出现这个问题

@SweetInk SweetInk self-assigned this Feb 20, 2022
@SweetInk
Copy link
Owner

SweetInk commented Feb 21, 2022

使用Mybatis时,无论是否以JRebel启动都会有上面的异常,我的建议是在Mapper里最好不要使用方法重载

从源码中我们也可以知道statementId = mapper.type.name + method.name。当执行mappedStatements#put时肯定会抛出异常

  public V put(String key, V value) {
      if (containsKey(key)) {
        throw new IllegalArgumentException(name + " already contains value for " + key
            + (conflictMessageProducer == null ? "" : conflictMessageProducer.apply(super.get(key), value)));
      }
      if (key.contains(".")) {
        final String shortKey = getShortName(key);
        if (super.get(shortKey) == null) {
          super.put(shortKey, value);
        } else {
          super.put(shortKey, (V) new Ambiguity(shortKey));
        }
      }
      return super.put(key, value);
    }

@SweetInk SweetInk removed the bug Something isn't working label Feb 21, 2022
@jiangjihui
Copy link
Author

jiangjihui commented Mar 3, 2022

是这样的,我使用的是github上的另外一个开源项目,项目地址是:https://github.com/YXJ2018/SpringBoot-Vue-OnlineExam ,我不使用jrebel启动,或者禁用本插件之后使用jrebel启动项目都是可以的,没有报任何错误。唯独在使用本插件之后,使用jrebel启动就报上面的错误了。楼主可下载该项目的后端代码在idea启动试一下就能看出来了。

我建了一个test类,测试了下,是可以进行重载的。都可以正常执行sql
image

@SweetInk
Copy link
Owner

SweetInk commented Mar 3, 2022

是这样的,我使用的是github上的另外一个开源项目,项目地址是:https://github.com/YXJ2018/SpringBoot-Vue-OnlineExam ,我不使用jrebel启动,或者禁用本插件之后使用jrebel启动项目都是可以的,没有报任何错误。唯独在使用本插件之后,使用jrebel启动就报上面的错误了。楼主可下载该项目的后端代码在idea启动试一下就能看出来了。

我建了一个test类,测试了下,是可以进行重载的。都可以正常执行sql image

下面是MybatisPlus重写的Configuration

com.baomidou.mybatisplus.core.MybatisConfiguration#addMappedStatement

    /**
     * MybatisPlus 加载 SQL 顺序:
     * <p>1、加载XML中的SQL</p>
     * <p>2、加载sqlProvider中的SQL</p>
     * <p>3、xmlSql 与 sqlProvider不能包含相同的SQL</p>
     * <p>调整后的SQL优先级:xmlSql > sqlProvider > curdSql</p>
     */
    @Override
    public void addMappedStatement(MappedStatement ms) {
        logger.debug("addMappedStatement: " + ms.getId());
        if (mappedStatements.containsKey(ms.getId())) {
            /*
             * 说明已加载了xml中的节点; 忽略mapper中的SqlProvider数据
             */
            logger.error("mapper[" + ms.getId() + "] is ignored, because it exists, maybe from xml file");
            return;
        }
        super.addMappedStatement(ms);
    }

之所以关掉插件不报错,是因为这个类重写了addMappedStatement方法,如果存在相同的statement-id,直接就会忽略,而插件是对这个类进行了代理,为了实现热加载对这个方法进行了重写,即直接调用父类的addmappedStatement方法。

你关掉插件,启动项目应该会有类似的输出
c.b.m.core.MybatisConfiguration : mapper[ExamManageMapper.findAll] is ignored, because it exists, maybe from xml file

@cxqweqwe
Copy link

cxqweqwe commented Jun 9, 2022

我也遇到了这个问题 我的mp版本是3.5.2

@SweetInk
Copy link
Owner

我也遇到了这个问题 我的mp版本是3.5.2

看我上面的回答。

@yanye666
Copy link

yanye666 commented Sep 4, 2023

我也遇到了这个问题 我的mp版本是3.5.2

看我上面的回答。

请问,是不修复这个问题吗,(虽然重载的写法本身就是坑)

@SweetInk
Copy link
Owner

我也遇到了这个问题 我的mp版本是3.5.2

看我上面的回答。

请问,是不修复这个问题吗,(虽然重载的写法本身就是坑)

目前不打算修复哦

@JackTonyMa
Copy link

大佬,我尝试处理了下,处理完的结果是不会reload重载的xml,正常的xml正常relaod,不会导致项目起不来,直接贴代码,看大佬是否能采纳.
ctClass.addField(CtField.make("private ArrayList __ignoreMapCache = new ArrayList();", ctClass)); //rewrite addMappedStatement String bodyStatement = ""; if (null != cp.getOrNull(Constants.MybatisConfiguration$StrictMapClass)) { bodyStatement = "{ if(__ignoreMapCache.contains($1.getId())){logger.warn(\"mapper[\" + $1.getId() + \"] reload fail, maybe it was overridden\"); return; }" + " if (mappedStatements.containsKey($1.getId()) && !isCustomResource($1.getResource())&&!reloader.isReloading()) {" + " logger.warn(\"mapper[\" + $1.getId() + \"] is ignored, because it exists , maybe from xml file or override\");" + " __ignoreMapCache.add($1.getId());" + " return;" + " }" + "mappedStatements.put($1.getId(), $1);}"; }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants