关于mybatis的org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
2017-09-25 20:09
821 查看
前言
今天遇到一个很郁闷的错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)。 奇怪的是我dao接口与mybatis映射文件配置都是正确的,但还是报错
正文
下面,我通过源码去探索一番。这次的探索之旅离不开debug,而项目是maven,所以在探索之前,必须得知道maven如何debug,具体文章在please click
准备工作差不多了,开始重现错误,报错入下:
定位214行
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) { String statementName = mapperInterface.getName() + "." + method.getName(); MappedStatement ms = null; if (configuration.hasStatement(statementName)) { ms = configuration.getMappedStatement(statementName); } else if (!mapperInterface.equals(method.getDeclaringClass())) { // issue #35 String parentStatementName = method.getDeclaringClass().getName() + "." + method.getName(); if (configuration.hasStatement(parentStatementName)) { ms = configuration.getMappedStatement(parentStatementName); } } if (ms == null) { if(method.getAnnotation(Flush.class) != null){ name = null; type = SqlCommandType.FLUSH; } else { throw new BindingException("Invalid bound statement (not found): " + statementName); } } else { name = ms.getId(); type = ms.getSqlCommandType(); if (type == SqlCommandType.UNKNOWN) { throw new BindingException("Unknown execution method for: " + name); } } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
从上面代码看两种途径binding,或者是配置文件,或者是注解。这里配置文件,问题出在configuration.hasStatement(statementName)为false. 进去看一下为什么会false
入下代码
public boolean hasStatement(String statementName, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.containsKey(statementName); }1
2
3
4
5
6
这里是发生本次异常比较关键的地方了,为什么我会说关键? 因为我从代码mappedStatements.containsKey(statementName); 中,可以看出2个会发生该异常的情况
mappedStatements为{} (空,debug发现,我这里为空)
containsKey(statementName),没有找到
mappedStatements为{}
先看第一点。 mappedStatements为什么是空的呢? 它是在什么时候初始化的呢。 在tomcat启动的时候,进入spring监听函数,里面将去解析spring配置文件,将去加载红框内的资源文件,解析并以key,value的形式缓存在mappedStatements中
具体缓存代码,在下面简单的罗列一下
XmlMapperBuilder方法的parse
public void parse() { if (!configuration.isResourceLoaded(resource)) { configurationElement(parser.evalNode("/mapper")); configuration.addLoadedResource(resource); bindMapperForNamespace(); } parsePendingResultMaps(); parsePendingChacheRefs(); parsePendingStatements(); }1
2
3
4
5
6
7
8
9
10
11
进入configurationElement方法,在选择其方法下的
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));1
类层次关系挺复杂的,有闲工夫就花类图理一下,最后找到下面MapperBuilderAssistant类中的addMappedStatement方法
MappedStatement statement = statementBuilder.build(); configuration.addMappedStatement(statement);1
2
解析完成了,我这次异常罪魁祸首,猜测是上面的红框内路径有问题,所以没缓存mappedStatements中(其实路径之前修改几次,最后是对的,只不过因为我eclipse取消自动编译,没编译,泪奔~)
在看源码的时候,我发现spring,将接口dao,动态代理了一个类,然后存入了IOC,所以我在service层,可以直接使用@Resource注入,至于如何将dao类存放到IOC中,不需要关心
从mappedStatements获取
上面讲过了将mybatis的映射文件缓存在mappedStatements中,具体key为ms.getId().public void addMappedStatement(MappedStatement ms) { mappedStatements.put(ms.getId(), ms); }1
2
3
这里的id规则是,mybatis映射文件的namespace + id,如下
<mapper namespace="org.personal.perfect.mpersistent.dao.TestMybatis"> <resultMap type="map" id="myinfo"></resultMap> <select id="selectInformation" parameterType="map" resultType="int"> select count(1) from information </select> <select id="selectInformationfor2" parameterType="map" resultType="map"> select * from information </select> <select id="selectInformationfor3" parameterType="map" resultType="map"> select * from information where id = #{id} </select> <select id="selectInformationfor4" parameterType="map" resultType="Information"> select * from information where id = #{id} </select> </mapper>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
而mappedStatements.containsKey(statementName)中的statementName获取的key规则是什么呢
String statementName = mapperInterface.getName() + "." + method.getName();1
也就是通过反射,获取类全路径限定名以及方法名,所以这也说明了接口名= namespace 方法名 = id. 赶紧检查一下吧
总结
1.spring与mybatis继承,配置自动扫描的话,赶紧看看资源路径是否对吧 2. dao接口名 = namespace ; 接口方法名 = id.
相关文章推荐
- 关于mybatis的org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
- 关于mybatis “org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)” 错误的问题。
- 关于mybatis “org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)” 错误的问题。
- 关于mybatis “org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)” 错误的问题
- 关于mybatis的org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
- Maven 遇到mybatis 发生org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
- Mybatis笔记二:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- MyBatis典型的错误org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- 关于mybatis “org.apache.ibatis.binding.BindingException: Invalid bound statement (
- mybatis绑定错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- mybatis错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- spring+mybatis整合报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- spring mybatis集成报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- 当mybatis整合spring后出现org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
- mybatis+springmvc:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- Idea+myBatis报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- mybatis maven打包出现org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误
- MyBatis笔记----报错:Exception in thread "main" org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决方法
- 关于org.apache.ibatis.binding.BindingException: Invalid bound statement (not found),找不到mapper文件问题解决
- mybatis绑定错误org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)