报错如标题所示,为了不耽误时间先给解决思路再唠起源
根据自己多年的经验本以为就是mapper没有扫到的原因,这也是网上大多数给的意见,事实上通过我的研究原因多种多样,具体如下:
上下求索
排查复盘
-
从报错日志中看是
SqlSessionTemplate
,没有顺利初始化导致
-
为了详细说明我们跟进去看看,是哪里初始化,注:以下就要分情况讨论了:
哦对了,在说明情况之前有个基础共识:如果你的项目是新项目,确实要看看有没有把你的包扫描进去,一般来说有两个操作步骤:-
1. 通过配置文件指定:
mybatis: mapper-locations: classpath*:mapper/**/*.xml
PS:你如果使用了mybatis-starter【1.7+】,那这一步是省略的
-
2. 通过@mapper指定扫描包范围:我习惯兜底遍历,这样保证一定没问题,牺牲了启动时间也还OK
@MapperScan(“com.company.**.mapper”)
-
3.
??? 怎么还有第三,那还不因为是新创建的项目,引入mybatis-starter时,默认注入配置: DataSourceAutoConfiguration,一些图省事的童鞋,直接在配置里排除注入,实际上也把sqlSessionTemplate注入也一并排除了,这才是天坑呀。
-
当然了如果是运营一段时间的老项目,你加入了一些其他配置也会导致这个问题,那么我们就要好好看看究竟是哪个老六,我目前遇到了加了两种依赖导致这个问题:
在MyBatis基础之上,引入MyBatisPlus【我就是这种情况】
通过开头的报错堆栈,跟进排查发现sqlSessionTemplate 的初始化交给了MybatisPlusAutoConfiguration
这只是从底层往上追溯,不太有说服力,那么我们直接打开springboot 的debug = true【这才是本文灵魂所在】 查看注入依赖,验证我们的结论;
果然not match,那么大部分情况看到这里解决方案也就明了,看看后面具体的提示即便也就了然于胸
而我这里大差不差,因为引入了sharding-jdbc 和 dynamic-datasource 导致引入两个同类型的datasourcce bean, 又没有指定优先级造成无法正确注入
因此本方案下的解决思路便是结合sharding 和 多数据源,具体配置我就不粘贴了照着官网或者配置文件:DynamicDataSourceProperties看就行了
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class})
public class DataSourceConfiguration {
public static final String SHARDING_DATASOURCE = "sync-sharding";
@Resource
private DynamicDataSourceProperties dynamicDataSourceProperties;
/**
* shardingjdbc有四种数据源,需要根据业务注入不同的数据源
*
* <p>1. 未使用分片, 脱敏的名称(默认): shardingDataSource;
* <p>2. 主从数据源: masterSlaveDataSource;
* <p>3. 脱敏数据源:encryptDataSource;
* <p>4. 影子数据源:shadowDataSource
*
* shardingjdbc默认就是shardingDataSource
*/
@Lazy
@Resource(name = "shardingDataSource")
private DataSource shardingDataSource;
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
// 多数据源的map
Map<String, DataSourceProperty> datasource = dynamicDataSourceProperties.getDatasource();
// 接管sharding
return new AbstractDataSourceProvider() {
@Override
public Map<String, DataSource> loadDataSources() {
Map<String, DataSource> dataSourceMap = createDataSourceMap(datasource);
dataSourceMap.put(SHARDING_DATASOURCE, shardingDataSource);
return dataSourceMap;
}
};
}
@Primary // 关键
@Bean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
dynamicRoutingDataSource.setP6spy(dynamicDataSourceProperties.getP6spy());
dynamicRoutingDataSource.setPrimary(dynamicDataSourceProperties.getPrimary());
dynamicRoutingDataSource.setSeata(dynamicDataSourceProperties.getSeata());
dynamicRoutingDataSource.setStrict(dynamicDataSourceProperties.getStrict());
dynamicRoutingDataSource.setStrategy(dynamicDataSourceProperties.getStrategy());
return dynamicRoutingDataSource;
}
}
怒发冲冠
至此,对于解决思路有了清晰的认识,但起初因为惰性思考导致耗费了不少时间和精力,甚至一度怀疑自己能力
其实早在错误堆栈出现的时候,就应该本能直接从结果上遍历,但因为几年顺利的开发经验告诉我 就是包没有扫入或者其他可以直接从网上就能得到的答案:思维惰性害己呀
思维惰性可能让我们离解决问题的道路渐行渐远,比如我甚至重新用mybaits搭建项目,因为懒得配置数据库,直接在配置文件跳过DataSourceAutoConfiguration的注入,发现还是注入不到sqlSessionTemplate 导致直接失去信心,而这也是因为对网上答案深信不疑一个多小时才猛然发现。
有的时候自带的调试框架如debug=true 真的指路明灯,当你仔细阅读一下才恍然大悟。
勤于思考吧 童鞋们~ 吾当共勉