自定义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文件

image.png | left | 634x226

所以需要找出来,读取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 方法中

image.png | left | 470x82.37871674491393

读取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)

image.png | left | 747x101

设置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
相关文章
|
Java 数据库连接 Maven
springboot集成mybatis时提示找不到Mapper Bean
springboot集成mybatis时提示找不到Mapper Bean
|
缓存 NoSQL Java
SpringBoot中RedisCluster的scan命令实践
线上环境redis key过期一直很头疼,自动过期用户可能会给用户展示过期数据无法忍受,可是又无法掌握固定的key,redis给我们提供了高性能的scan操作,可千万不能用keys * 了! SpringBoot2.0升级使用lettuce替换了jedis为默认的reids连接工具。
3328 0
|
Java 数据库连接 mybatis
成功解决: Invalid bound statement (not found) 在已经使用mybatis的项目里引入mybatis-plus,结果不能共存的解决
这篇文章讨论了在已使用MyBatis的项目中引入MyBatis-Plus后出现的"Invalid bound statement (not found)"错误,并提供了解决方法,主要是通过修改yml配置文件来解决MyBatis和MyBatis-Plus共存时的冲突问题。
成功解决: Invalid bound statement (not found) 在已经使用mybatis的项目里引入mybatis-plus,结果不能共存的解决
|
XML Java Maven
Invalid bound statement (not found)
Invalid bound statement (not found)
359 0
|
XML Java 关系型数据库
Springboot启动时报错Property ‘mapperLocations‘ was not specified.
Springboot启动时报错Property ‘mapperLocations‘ was not specified.
839 2
|
XML Java 数据库连接
解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题
解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题
15068 2
解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题
SpringBoot:Invalid bound statement (not found)的原因和解决方案
SpringBoot:Invalid bound statement (not found)的原因和解决方案
|
SQL Java 数据库
10、MyBatis-Plus 多数据源
这篇文章介绍了在MyBatis-Plus中实现多数据源的方法,包括创建不同的数据库和表、引入动态数据源依赖、配置多个数据源、创建用户和商品的Service类,以及如何进行测试来验证多数据源的功能。
Invalid bound statement (not found)错误【已解决】
Invalid bound statement (not found)错误【已解决】
3153 1
|
Java 数据库连接 数据库
【Spring技术专题】「实战开发系列」保姆级教你SpringBoot整合Mybatis框架实现多数据源的静态数据源和动态数据源配置落地
Mybatis是一个基于JDBC实现的,支持普通 SQL 查询、存储过程和高级映射的优秀持久层框架,去掉了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索封装。 Mybatis主要思想是将程序中大量的 SQL 语句剥离出来,配置在配置文件中,以实现 SQL 的灵活配置。在所有 ORM 框架中都有一个非常重要的媒介——PO(持久化对象),PO 的作用就是完成持久化操作,通过该对象对数据库执行增删改的操作,以面向对象的方式操作数据库。
501 1
【Spring技术专题】「实战开发系列」保姆级教你SpringBoot整合Mybatis框架实现多数据源的静态数据源和动态数据源配置落地

热门文章

最新文章