mybatis错误之Could not find result map java.util.List

本文解析了一个关于MyBatis中使用resultMap时出现的错误,详细介绍了错误发生的情景,包括如何复现错误,错误的具体表现,以及如何解决此问题。文章指出,在调用一个正常的方法时,可能会因为另一个未调用但配置错误的方法而引发异常,这需要开发者检查所有相关的方法配置。

1.复现错误

报错提示:

13:41:33.539 ERROR com.fast.framework.advice.FastBootControllerAdvice 58 errorHandler - Could not find result map java.util.List org.apache.ibatis.builder.IncompleteElementException: Could not find result map java.util.List
	at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:346) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:290) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:109) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.session.Configuration.lambda$buildAllStatements$2(Configuration.java:787) ~[mybatis-3.5.0.jar:3.5.0]
	at java.util.Collection.removeIf(Collection.java:414) ~[?:1.8.0_112]
	at org.apache.ibatis.session.Configuration.buildAllStatements(Configuration.java:786) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:763) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:758) ~[mybatis-3.5.0.jar:3.5.0]
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod$SqlCommand.resolveMappedStatement(MybatisMapperMethod.java:264) ~[mybatis-plus-core-3.1.0

2.背景

首先去官网确认一下resultMap和resultType的用法自己用对了,本文不讨论基本用法,所以针对已经熟练运用myabtis后的错误

官网:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#select

3.复现场景

(1)Dao层有两个方法,记住这两个fast是正常的,test是错误的

int selectFast();

int selectTest();

(2)对应xml,其中selectTest是有问题的, resultMap="java.util.List" 这样写是错误的

<select id="selectFast" resultType="java.lang.Integer">
    select count(1) from sys_user
</select>

<select id="selectTest" resultMap="java.util.List">
    select count(1) from sys_user
</select>

(3)然后我只调用正常的那个方法int selectFast();

masterDao.selectFast()

(4)正常的maven   clean,install,package都正常

(5)编译完启动,也正常启动

(6)然后在通过controller调用正常的方法selectFast的时候报最开始那个错了

Could not find result map java.util.List

(7)类似这个错误会有个提示错误发生的位置,这个错误的提示是:

at com.fast.web.controller.TestController.getString(TestController.java:25) ~[classes/:?]

就是这个TestController的25行,我也是调用的这个方法,按理说都正确

(8)但是不正确的问题是哪里?

我当前调用的这个方法int selectFast();是正常的啊,代码没有问题,并且调用的接口也只是这个方法,所以代码应该正常执行啊。

但是mybatis返回错误了,返回了一个与当时接口调用,不相干的一个方法(int selectTest();)的错误,然而这个错误,在编译阶段,启动阶段都没有报错。在调用其他方法的时候,提示了这个方法的错误,并且提示的有错误的位置是正确方法的位置。

思路:先解决问题再搞清问题,直接把不相干方法的错误改掉,如下修改,int selectTest();方法正常,再次访问提示正常。

<select id="selectTest" resultType="java.lang.Integer">
    select count(1) from sys_user
</select>

当时的解决思路debug:因为我请求的正常方法,返回参数应该是resultType的,但是这个resultMap是哪里来的,并且还报错了,看mybatis提示错误信息位置,

14:04:46.787 ERROR com.fast.framework.advice.FastBootControllerAdvice 58 errorHandler - Could not find result map java.util.List org.apache.ibatis.builder.IncompleteElementException: Could not find result map java.util.List
	at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:346) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:290) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:109) ~[mybatis-3.5.0.jar:3.5.0]
	at org.apache.ibatis.session.Configuration.lambda$buildAllStatements$2(Configuration.java:787) ~[mybatis-3.5.0.jar:3.5.0]
	at java.util.Collection.removeIf(Collection.java:414) ~[?:1.8.0_112]

找到这个(XMLStatementBuilder.java:109)打个断点,下面是mybatis源码,断点位置放在最后一行。

重新请求,看发过来的resultMap参数

 public void parseStatementNode() {
        String id = this.context.getStringAttribute("id");
        String databaseId = this.context.getStringAttribute("databaseId");
        if (this.databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
            Integer fetchSize = this.context.getIntAttribute("fetchSize");
            Integer timeout = this.context.getIntAttribute("timeout");
            String parameterMap = this.context.getStringAttribute("parameterMap");
            String parameterType = this.context.getStringAttribute("parameterType");
            Class<?> parameterTypeClass = this.resolveClass(parameterType);
            String resultMap = this.context.getStringAttribute("resultMap");
            String resultType = this.context.getStringAttribute("resultType");
            String lang = this.context.getStringAttribute("lang");
            LanguageDriver langDriver = this.getLanguageDriver(lang);
            Class<?> resultTypeClass = this.resolveClass(resultType);
            String resultSetType = this.context.getStringAttribute("resultSetType");
            StatementType statementType = StatementType.valueOf(this.context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
            ResultSetType resultSetTypeEnum = this.resolveResultSetType(resultSetType);
            String nodeName = this.context.getNode().getNodeName();
            SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
            boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
            boolean flushCache = this.context.getBooleanAttribute("flushCache", !isSelect);
            boolean useCache = this.context.getBooleanAttribute("useCache", isSelect);
            boolean resultOrdered = this.context.getBooleanAttribute("resultOrdered", false);
            XMLIncludeTransformer includeParser = new XMLIncludeTransformer(this.configuration, this.builderAssistant);
            includeParser.applyIncludes(this.context.getNode());
            this.processSelectKeyNodes(id, parameterTypeClass, langDriver);
            SqlSource sqlSource = langDriver.createSqlSource(this.configuration, this.context, parameterTypeClass);
            String resultSets = this.context.getStringAttribute("resultSets");
            String keyProperty = this.context.getStringAttribute("keyProperty");
            String keyColumn = this.context.getStringAttribute("keyColumn");
            String keyStatementId = id + "!selectKey";
            keyStatementId = this.builderAssistant.applyCurrentNamespace(keyStatementId, true);
            Object keyGenerator;
            if (this.configuration.hasKeyGenerator(keyStatementId)) {
                keyGenerator = this.configuration.getKeyGenerator(keyStatementId);
            } else {
                keyGenerator = this.context.getBooleanAttribute("useGeneratedKeys", this.configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
            }

            this.builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, (KeyGenerator)keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
        }
    }

然后查看debug参数,我这个接口请求的是selectFast()的啊,正常的方法,但是现在也校验了selectTest();这个有问题的方法。

resultMap返回java.util.List

所以全局搜selectTest这个方法,修改返回参数,完成bug修复。

总结:这个bug不是什么比较复杂的bug,也不是什么有意义的bug,但是mybatis编译,启动都不报错,在请求正常接口的时候,报一个不相干方法的错误,这个提示位置是有问题的,就会导致大家排查问题浪费大量时间,先记住会有这个问题吧,以后会避免一个坑。

 

"C:\Program Files\Java\jdk-9.0.4\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\2025zjwdezuoye\IntelliJ IDEA 2020.1\lib\idea_rt.jar=64683:D:\2025zjwdezuoye\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "D:\2025zjwdezuoye\IntelliJ IDEA 2020.1\lib\idea_rt.jar;D:\2025zjwdezuoye\IntelliJ IDEA 2020.1\plugins\junit\lib\junit5-rt.jar;D:\2025zjwdezuoye\IntelliJ IDEA 2020.1\plugins\junit\lib\junit-rt.jar;C:\Users\86177\mybatistest\target\test-classes;C:\Users\86177\mybatistest\target\classes;C:\Users\86177\.m2\repository\org\mybatis\mybatis\3.5.2\mybatis-3.5.2.jar;C:\Users\86177\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\86177\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\86177\.m2\repository\mysql\mysql-connector-java\8.0.11\mysql-connector-java-8.0.11.jar;C:\Users\86177\.m2\repository\com\google\protobuf\protobuf-java\2.6.0\protobuf-java-2.6.0.jar;C:\Users\86177\.m2\repository\log4j\log4j\1.2.12\log4j-1.2.12.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 Test.PersonTest,test1 org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.apache.ibatis.builder.IncompleteElementException: Could not find result map 'com.itheima.mapper.IdCardMapper.studentMap' referenced from 'com.itheima.mapper.IdCardMapper.findAllStudent' ### Cause: org.apache.ibatis.builder.IncompleteElementException: Could not find result map 'com.itheima.mapper.IdCardMapper.studentMap' referenced from 'com.itheima.mapper.IdCardMapper.findAllStudent' at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76) at Test.PersonTest.test1(PersonTest.java:16) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58) Caused by: org.apache.ibatis.builder.IncompleteElementException: Could not find result map 'com.itheima.mapper.IdCardMapper.studentMap' referenced from 'com.itheima.mapper.IdCardMapper.findAllStudent' at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:341) at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:285) at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:113) at org.apache.ibatis.session.Configuration.lambda$buildAllStatements$2(Configuration.java:816) at java.base/java.util.Collection.removeIf(Collection.java:414) at org.apache.ibatis.session.Configuration.buildAllStatements(Configuration.java:815) at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:753) at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:748) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:146) ... 25 more Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for com.itheima.mapper.IdCardMapper.studentMap at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:964) at org.apache.ibatis.session.Configuration.getResultMap(Configuration.java:674) at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:339) ... 33 more 进程已结束,退出代码 -1
09-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值