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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java web文件下载断点续传
下一篇:面试请不要再问我Spring Cloud底层原理

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月17日 18时56分41秒