天天看點

自定義SqlSessionFactoryBean導緻 mapper-locations 失效

問題重制

步驟

1,把所有的mapper xml移動到 /xxx/yyy/src/main/resources/mybatis/mapperxml 中;

2,修改application.properties ,添加:

mybatis.mapper-locations=classpath:**/mapperxml/*.xml           

3,啟動springboot 程式 com/test/xxx/app/nnn/Application.java

4,通路接口

http://127.0.0.1:/nnn/productManage/listYYs.json?ccKey=Key222&vvName=%AF%B7%E5%81%87App

報錯:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):           

初步分析

根據現象推斷出,spring boot 沒有讀取我的 mybatis mapper xml檔案

自定義SqlSessionFactoryBean導緻 mapper-locations 失效

是以需要找出來,讀取mybatis mapper xml檔案 的邏輯在哪裡,為什麼沒有讀取?

定位問題過程

讀取mapper xml檔案 的邏輯/位置

/repository/org/mybatis/mybatis-spring/1.3.2/mybatis-spring-1.3.2-sources.jar!/org/mybatis/spring/SqlSessionFactoryBean.java的

protected SqlSessionFactory buildSqlSessionFactory() throws IOException 方法中

自定義SqlSessionFactoryBean導緻 mapper-locations 失效

讀取mapper xml檔案的邏輯

if (!isEmpty(this.mapperLocations)) {
      for (Resource mapperLocation : this.mapperLocations) {
        if (mapperLocation == null) {
          continue;
        }
          XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
              configuration, mapperLocation.toString(), configuration.getSqlFragments());
          xmlMapperBuilder.parse();
      }
    } else {
      if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");
      }
    }           

通過IDEA 調試到這兒的時候,發現 this.mapperLocations 為null,是以才沒有走這個邏輯

為什麼this.mapperLocations 為null

this.mapperLocations 是在哪裡設定的呢?

在 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 類中,

sqlSessionFactory(DataSource dataSource)           
自定義SqlSessionFactoryBean導緻 mapper-locations 失效

設定this.mapperLocations的代碼:

if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
      factory.setMapperLocations(this.properties.resolveMapperLocations());
    }           

之是以沒有執行MybatisAutoConfiguration 中的 sqlSessionFactory(DataSource dataSource) throws Exception 方法,是因為

SqlSessionFactoryBean           

是我們定制的,沒有依賴系統生成.

我們自定義生成SqlSessionFactoryBean 對象

final SqlSessionFactoBean sessionFactoryBean = new SqlSessionFactoBean();

sessionFactoryBean.setDataSource(aaaGroupDataSource);

SqlSessionFactory sqlSessionFactory = sessionFactoryBean.getObject();
// mybatis自動通用字段自動設定配置
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();

return sqlSessionFactory;           

系統構造SqlSessionFactory

在/repository/org/mybatis/mybatis-spring/1.3.6/mybatis-spring-1.3.6-sources.jar!/org/mybatis/spring/SqlSessionFactoryBean.java 的

protected SqlSessionFactory buildSqlSessionFactory() throws IOException           

原因總結

因為我們自定義生成 SqlSessionFactoryBean對象 導緻沒有執行org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 類的sqlSessionFactory(DataSource dataSource)方法

解決方法

手動添加設定this.mapperLocations 的邏輯即可:

final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();

//解決 application.properties 中 配置mybatis.mapper-locations 失效的問題
if (!ObjectUtils.isEmpty(this.mybatisProperties.resolveMapperLocations())) {
    sessionFactoryBean.setMapperLocations(this.mybatisProperties.resolveMapperLocations());
}
sessionFactoryBean.setDataSource(aaaGroupDataSource);

SqlSessionFactory sqlSessionFactory = sessionFactoryBean.getObject();
// mybatis自動通用字段自動設定配置
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
// 。。。

return sqlSessionFactory;           

//解決 application.properties 中 配置mybatis.mapper-locations 失效的問題

<span data-type="color" style="color:#F5222D">if (!ObjectUtils.isEmpty(this.mybatisProperties.resolveMapperLocations())) {</span>           

sessionFactoryBean.setMapperLocations(this.mybatisProperties.resolveMapperLocations());

}

tips

若想親自調試,可以關注如下類:

  1. org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
  2. org.mybatis.spring.SqlSessionFactoryBean
  3. org.apache.ibatis.session.SqlSessionFactoryBuilder