SpringBoot2.1.9 Mybatis由于@Mapper注解多数据源配置不生效问题
发布日期:2021-07-01 01:16:04
浏览次数:2
分类:技术文章
本文共 21380 字,大约阅读时间需要 71 分钟。
一、场景复现
(1)项目
目录
配置文件
spring: application: name: multi-datasource profiles: active: dev1 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/base?autoReconnect=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8 username: root password: adminmybatis: mapper-locations: classpath*:mapper/base/*.xml type-aliases-package: com.mk.mybatis.multidatasource configuration: map-underscore-to-camel-case: truesys: one-mybatis: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/man?autoReconnect=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8 username: root password: admin mybatis: mapper-locations: classpath*:mapper/one/*.xml type-aliases-package: com.mk.mybatis.multidatasource.one.entity configuration: map-underscore-to-camel-case: true two-mybatis: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/person?autoReconnect=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8 username: root password: admin mybatis: mapper-locations: classpath*:mapper/two/*.xml type-aliases-package: com.mk.mybatis.multidatasource.two.entity configuration: map-underscore-to-camel-case: trueserver: port: 8080
pom.xml
4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.9.RELEASE com.mk.mybatis multi-datasource 1.0-SNAPSHOT multi-datasource MybatisMultiDataSource 1.8 org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true mysql mysql-connector-java 5.1.48 org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.0 com.alibaba druid 1.1.20 org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.boot spring-boot-starter-web 2.1.9.RELEASE tk.mybatis mapper-spring-boot-starter 2.1.5 javax.persistence persistence-api org.springframework.boot spring-boot-maven-plugin org.mybatis.generator mybatis-generator-maven-plugin 1.3.7 org.mybatis.generator mybatis-generator-core 1.3.7 true true generatorConfig1.xml
继承mybatis生成器生成的dao类
@Mapperpublic interface DaseDao extends IBaseDao {}
@Mapperpublic interface ManDao extends IManDao {}
@Mapperpublic interface PersonDao extends IPersonDao {}
默认mybatis数据源配置
@Configuration@MapperScan(value = "com.mk.mybatis.multidatasource.base.dao", sqlSessionTemplateRef = "baseSqlSessionTemplate")public class BaseMybatisConfig { @Primary @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSourceProperties baseDataSourceProperties() { return new DataSourceProperties(); } @Primary @Bean("datasource") public DataSource baseDataSource(@Qualifier("baseDataSourceProperties") DataSourceProperties dataSourceProperties) { DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build(); return dataSource; } @Primary @Bean @ConfigurationProperties(prefix = "mybatis") public MybatisProperties baseMybatisProperties() { return new MybatisProperties(); } @Primary @Bean public SqlSessionFactory baseSqlSessionFactory(@Qualifier("datasource") DataSource dataSource, @Qualifier("baseMybatisProperties") MybatisProperties mybatisProperties) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(mybatisProperties.resolveMapperLocations()); bean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackage()); bean.setConfigurationProperties(mybatisProperties.getConfigurationProperties()); bean.setConfiguration(mybatisProperties.getConfiguration()); bean.setConfigLocation(Optional.ofNullable(mybatisProperties.getConfigLocation()).map(location -> { try { ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); return resourceResolver.getResource(location); } catch (Exception var3) { return null; } }).orElse(null)); return bean.getObject(); } @Primary @Bean public DataSourceTransactionManager transactionManager(@Qualifier("datasource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Primary @Bean public SqlSessionTemplate baseSqlSessionTemplate(@Qualifier("baseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); }
one mybatis数据源配置
@Configuration@MapperScan(value = "com.mk.mybatis.multidatasource.one.dao", sqlSessionTemplateRef = "oneSqlSessionTemplate")@Slf4jpublic class OneMybatisConfig { @Bean @ConfigurationProperties(prefix = "sys.one-mybatis.datasource") public DataSourceProperties oneDataSourceProperties() { return new DataSourceProperties(); } @Bean public DataSource oneDataSource(@Qualifier("oneDataSourceProperties") DataSourceProperties dataSourceProperties) { DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build(); return dataSource; } @Bean @ConfigurationProperties(prefix = "sys.one-mybatis.mybatis") public MybatisProperties oneMybatisProperties(){ return new MybatisProperties(); } @Bean public SqlSessionFactory oneSqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource, @Qualifier("oneMybatisProperties")MybatisProperties mybatisProperties)throws Exception{ SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(mybatisProperties.resolveMapperLocations()); bean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackage()); bean.setConfigurationProperties(mybatisProperties.getConfigurationProperties()); bean.setConfiguration(mybatisProperties.getConfiguration()); bean.setConfigLocation(Optional.ofNullable(mybatisProperties.getConfigLocation()).map(location->{ try { ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); return resourceResolver.getResource(location); } catch (Exception var3) { return null; } }).orElse(null)); return bean.getObject(); } @Bean public DataSourceTransactionManager oneTransactionManager(@Qualifier("oneDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionTemplate oneSqlSessionTemplate(@Qualifier("oneSqlSessionFactory") SqlSessionFactory sqlSessionFactory){ return new SqlSessionTemplate(sqlSessionFactory); }}
two mybatis数据源配置
@Configuration@MapperScan(value = "com.mk.mybatis.multidatasource.two.dao", sqlSessionTemplateRef = "twoSqlSessionTemplate")@Slf4jpublic class TwoMybatisConfig { @Bean @ConfigurationProperties(prefix = "sys.two-mybatis.datasource") public DataSourceProperties twoDataSourceProperties() { return new DataSourceProperties(); } @Bean public DataSource twoDataSource(@Qualifier("twoDataSourceProperties") DataSourceProperties dataSourceProperties) { DataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().build(); return dataSource; } @Bean @ConfigurationProperties(prefix = "sys.two-mybatis.mybatis") public MybatisProperties twoMybatisProperties() { return new MybatisProperties(); } @Bean public SqlSessionFactory twoSqlSessionFactory(@Qualifier("twoDataSource") DataSource dataSource, @Qualifier("twoMybatisProperties") MybatisProperties mybatisProperties) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(mybatisProperties.resolveMapperLocations()); bean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackage()); bean.setConfigurationProperties(mybatisProperties.getConfigurationProperties()); bean.setConfiguration(mybatisProperties.getConfiguration()); bean.setConfigLocation(Optional.ofNullable(mybatisProperties.getConfigLocation()).map(location -> { try { ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); return resourceResolver.getResource(location); } catch (Exception var3) { return null; } }).orElse(null)); return bean.getObject(); } @Bean public DataSourceTransactionManager twoTransactionManager(@Qualifier("twoDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionTemplate twoSqlSessionTemplate(@Qualifier("twoSqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); }}
(2)测试类
BaseDao
@Resource private DaseDao baseDao; @Test public void testBaseDao() { System.out.println(baseDao.selectByPrimaryKey(1)); }
输出
2020-05-04 21:03:21,174 DEBUG [main] 5363 com.mk.mybatis.multidatasource.base.base.dao.IBaseDao.selectByPrimaryKey[143]: ==> Preparing: select id, `name` from base where id = ? 2020-05-04 21:03:21,205 DEBUG [main] 5394 com.mk.mybatis.multidatasource.base.base.dao.IBaseDao.selectByPrimaryKey[143]: ==> Parameters: 1(Integer)2020-05-04 21:03:21,221 DEBUG [main] 5410 com.mk.mybatis.multidatasource.base.base.dao.IBaseDao.selectByPrimaryKey[143]: <== Total: 0null
debug看到的数据源
PersonDao
@Resource private PersonDao personDao; @Test public void testPersonDao() { System.out.println(personDao.selectByPrimaryKey(1)); }
输出
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.mk.mybatis.multidatasource.two.dao.PersonDao.selectByPrimaryKey at org.apache.ibatis.binding.MapperMethod$SqlCommand.(MapperMethod.java:235) at org.apache.ibatis.binding.MapperMethod. (MapperMethod.java:53) at org.apache.ibatis.binding.MapperProxy.lambda$cachedMapperMethod$0(MapperProxy.java:61) at org.apache.ibatis.binding.MapperProxy$$Lambda$443/448131210.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:61) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:56) at com.sun.proxy.$Proxy67.selectByPrimaryKey(Unknown Source) at com.mk.mybatis.multidatasource.MultiDatasourceApplicationTests.testPersonDao(MultiDatasourceApplicationTests.java:34) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
debug看到的数据源
ManDao
@Resource private ManDao manDao; @Test public void testManDao() { System.out.println(manDao.selectByPrimaryKey(1)); }
输出:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.mk.mybatis.multidatasource.one.dao.ManDao.selectByPrimaryKey at org.apache.ibatis.binding.MapperMethod$SqlCommand.(MapperMethod.java:235) at org.apache.ibatis.binding.MapperMethod. (MapperMethod.java:53) at org.apache.ibatis.binding.MapperProxy.lambda$cachedMapperMethod$0(MapperProxy.java:61) at org.apache.ibatis.binding.MapperProxy$$Lambda$443/736951628.apply(Unknown Source) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:61) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:56) at com.sun.proxy.$Proxy68.selectByPrimaryKey(Unknown Source) at com.mk.mybatis.multidatasource.MultiDatasourceApplicationTests.testManDao(MultiDatasourceApplicationTests.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
debug看到的数据源
(3)分析
从上面的测试结果来看,多数据源配置不生效。
然而去掉PersonDao和ManDao的@Mapper注解,多数据源配置就生效了
PersonDao
//@Mapperpublic interface PersonDao extends IPersonDao {}
2020-05-04 21:26:18,477 DEBUG [main] 4644 com.mk.mybatis.multidatasource.two.base.dao.IPersonDao.selectByPrimaryKey[143]: ==> Preparing: select id, `name` from person where id = ? 2020-05-04 21:26:18,497 DEBUG [main] 4664 com.mk.mybatis.multidatasource.two.base.dao.IPersonDao.selectByPrimaryKey[143]: ==> Parameters: 1(Integer)2020-05-04 21:26:18,506 DEBUG [main] 4673 com.mk.mybatis.multidatasource.two.base.dao.IPersonDao.selectByPrimaryKey[143]: <== Total: 0null
ManDao
//@Mapperpublic interface ManDao extends IManDao {}
2020-05-04 21:31:04,470 DEBUG [main] 4413 com.mk.mybatis.multidatasource.one.base.dao.IManDao.selectByPrimaryKey[143]: ==> Preparing: select id, `name` from man where id = ? 2020-05-04 21:31:04,499 DEBUG [main] 4442 com.mk.mybatis.multidatasource.one.base.dao.IManDao.selectByPrimaryKey[143]: ==> Parameters: 1(Integer)2020-05-04 21:31:04,513 DEBUG [main] 4456 com.mk.mybatis.multidatasource.one.base.dao.IManDao.selectByPrimaryKey[143]: <== Total: 0null
二、原由
由于使用了tk.mybatis的包,默认自动全包扫描@Mapper注解。tk.mybatis扫描生成的Mapper比其他自定义配置的bean生成对应的Mapper对象快,而自定义的mybatis@MapperScan后扫描,Dao Bean已经生成了,无法再指定数据源进行注入了。
三、解决方案
(1)去掉tk.mybatis
tk.mybatis mapper-spring-boot-starter 2.1.5 javax.persistence persistence-api
(2)不加@Mapper注解
//@Mapperpublic interface PersonDao extends IPersonDao {}
转载地址:https://maokun.blog.csdn.net/article/details/105465261 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2024年04月17日 18时56分41秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
source insight快捷键及使用技巧
2019-05-01
映 射 ALT 键
2019-05-01
vim使用快捷键F4生成文件头注释、F5生成main函数模板、F6生成.h文件框架模板
2019-05-01
idea 热部署 jrebel 详细配置
2019-05-01
特殊符号大全!
2019-05-01
csdn如何自定义博客栏目
2019-05-01
CSDN博客专栏申请方法
2019-05-01
CSDN博客页面自定义左侧博客栏目
2019-05-01
分布式缓存系统Memcached简介与实践
2019-05-01
IntelliJ IDEA中怎么恢复本地代码
2019-05-01
maven 阿里云 国内镜像 中央仓库
2019-05-01
用python解析html
2019-05-01
OV5620的视频驱动
2019-05-01
C++中两个类交叉定义或递归定义的解决办法
2019-05-01
String.format详解
2019-05-01
JSONObject、JSONArray
2019-05-01
JSON parse 错误: unexpected token at分析和解决
2019-05-01
python built-in function summary
2019-05-01
对于git/热部署/创建maven工程的小记录
2019-05-01