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;
  }

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM