mybatis源码分析——常见错误异常分析

 

1:根据sqlId没有找到对应的MapperStatement,有可能是sql语句不存在、或者sqlId的名字和mapper方法中的名字对不上

Exception in thread "main" org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.example.mybatis.mapper.UserMapper.listUsers
	at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:196)
	at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:44)
	at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:59)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52)
	at com.sun.proxy.$Proxy0.listUsers(Unknown Source)
	at com.example.mybatis.TestMybatis.main(TestMybatis.java:27)

  

从异常的栈信息中,可以看到调用listUsers方法,会调用到代理的invoke方法

List<User> list =  userMapper.listUsers("hello105");

调到invoke这个方法:
final MapperMethod mapperMethod = cachedMapperMethod(method);

实例化MapperMethod对象:
private MapperMethod cachedMapperMethod(Method method) {
  MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}

实例化sqlCommand对象:
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, method);
}

 

 

 

2:mapper.xml 中 ,元素重复的问题,有可能是 resultMap 重复,sql、或者 select等元素重复,也有可能jar包重复了,或者名字重复等

Caused by: java.lang.IllegalArgumentException: Result Maps collection already contains value for com.example.mybatis.mapper.UserMapper.test
	at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:816)
	at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:788)
	at org.apache.ibatis.session.Configuration.addResultMap(Configuration.java:570)
	at org.apache.ibatis.builder.MapperBuilderAssistant.addResultMap(MapperBuilderAssistant.java:214)
	at org.apache.ibatis.builder.ResultMapResolver.resolve(ResultMapResolver.java:47)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:285)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:252)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElements(XMLMapperBuilder.java:244)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:116)
	... 7 more

  

之前的章节我们说过,XMLMapperBuilder是专门用来解析mapper.xml文件,下面我们来从源码的层面分析一下:

从栈信息中可以看出,

 

 

 找到解析resultMap元素的方法:

 

 

 

resultMap的节点会在resultMapElement方法中解析:

 

 

 

 

 

 

解析后会向configuration中resultMap的缓存中放,由于id重复,所以会抛出异常

 

 

 抛出异常信息的逻辑:

 

 

 

3:看下面的异常,提示ResultMap缓存中没有userMapper.test的元素

 

Exception in thread "main" Disconnected from the target VM, address: '127.0.0.1:52974', transport: 'socket'
org.apache.ibatis.builder.IncompleteElementException: Could not find result map UserMapper.test
	at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:346)
	at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:290)
	at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parseStatement(MapperAnnotationBuilder.java:317)
	at org.apache.ibatis.builder.annotation.MethodResolver.resolve(MethodResolver.java:33)
	at org.apache.ibatis.session.Configuration.buildAllStatements(Configuration.java:738)
	at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:702)
	at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:697)
	at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:183)
	at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:44)
	at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:59)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52)
	at com.sun.proxy.$Proxy3.selectUser(Unknown Source)
	at com.example.mybatis.TestMybatis.main(TestMybatis.java:27)
Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for UserMapper.test
	at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:832)
	at org.apache.ibatis.session.Configuration.getResultMap(Configuration.java:584)
	at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:344)
	... 12 more

  

这个异常是因为resultMap的名称对应不上,要么直接写test简称,要么直接全路径名

 

 

不能写成其他的名字,下面通过分析源码的形式看一下为什么报错:

 

 

 

 

 

 

 

 

 

 

 

这里有个应用命名空间的方法:

 

 

如果base是只有带命名空间直接返回,如果包含点,抛异常,如果不带命名空间,则拼接命名空间与方法名,所以resultMap上面的名称要么简写,要么全路径名称。

  public String applyCurrentNamespace(String base, boolean isReference) {
    if (base == null) {
      return null;
    }
    if (isReference) {
      // is it qualified with any namespace yet?
      if (base.contains(".")) {
        return base;
      }
    } else {
      // is it qualified with this namespace yet?
      if (base.startsWith(currentNamespace + ".")) {
        return base;
      }
      if (base.contains(".")) {
        throw new BuilderException("Dots are not allowed in element names, please remove it from " + base);
      }
    }
    return currentNamespace + "." + base;
  }

  

 

posted @ 2020-06-11 16:28  warrior1234  阅读(1385)  评论(0编辑  收藏  举报