您现在的位置是:首页 > 文章详情

自定义SqlSessionFactoryBean导致 mapper-locations 失效

日期:2020-04-08点击:1452

问题重现

步骤
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
原文链接:https://yq.aliyun.com/articles/754124
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章