在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法
2018-01-16 11:32
986 查看
1. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
在使用了动态数据源后遇到了该问题,从错误信息来看是因为没有找到
确实添加了相关的配置,这种错误的原因是因为设置数据源后没有设置
和
解决方法:*.xml文件而导致的,但是在配置文件中
确实添加了相关的配置,这种错误的原因是因为设置数据源后没有设置
SqlSessionFactoryBean的
typeAliasesPackage
和
mapperLocations属性或属性无效导致的;
如果在应用的入口类中添加了
在
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class),
在
DataSourceConfigure类的中设置相关属性:
@Bean @ConfigurationProperties(prefix = "mybatis") public SqlSessionFactoryBean sqlSessionFactoryBean() { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dynamicDataSource()); return sqlSessionFactoryBean; }或者直接配置(不推荐该方式):
@Bean public SqlSessionFactoryBean sqlSessionFactoryBean() { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setTypeAliasesPackage("typeAliasesPackage"); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("mapperLocations")); sqlSessionFactoryBean.setDataSource(dynamicDataSource()); return sqlSessionFactoryBean; }
2. Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
该异常在错误信息中已经说的很清楚了,是因为有多个
解决方法:DataSource的实例,所以无法确定该引用那个实例
为数据源的某个
得到的
或
Bean添加
@Primary注解,该
Bean应当是通过
DataSourceBuilder.create().build()
得到的
Bean,而不是通过
new AbstractRoutingDataSource的子类实现的
Bean,在本项目中可以是
master()
或
slave()得到的
DataSource,不能是
dynamicDataSource()得到的
DataSource
3. 通过注解方式动态切换数据源无效
请确认注解没有放到 DAO 层方法上, 因为会在 Service 层开启事务,所以当注解在 DAO 层时不会生效请确认以下
Bean正确配置:
@Bean("dynamicDataSource") public DataSource dynamicDataSource() { DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource(); Map<Object, Object> dataSourceMap = new HashMap<>(2); dataSourceMap.put("master", master()); dataSourceMap.put("slave", slave()); // Set master datasource as default dynamicRoutingDataSource.setDefaultTargetDataSource(master()); // Set master and slave datasource as target datasource dynamicRoutingDataSource.setTargetDataSources(dataSourceMap); // To put datasource keys into DataSourceContextHolder to judge if the datasource is exist DynamicDataSourceContextHolder.dataSourceKeys.addAll(dataSourceMap.keySet()); } return dynamicRoutingDataSource; } @Bean @ConfigurationProperties(prefix = "mybatis") public SqlSessionFactoryBean sqlSessionFactoryBean() { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); // Here is very important, if don't config this, will can't switch datasource // put all datasource into SqlSessionFactoryBean, then will autoconfig SqlSessionFactory sqlSessionFactoryBean.setDataSource(dynamicDataSource()); return sqlSessionFactoryBean; }
4. @Transactional
注解无效,发生异常不回滚
请确认该 Bean得到正确配置,并且
@Transactional的
rollbackFor配置正确
@Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dynamicDataSource()); }
5. 通过 AOP 判断 DAO 层方法名时切换数据源无效
当切面指向了 DAO 层后无论如何设置切面的顺序,都无法在执行查询之前切换数据源,但是切面改为 Service 层后可以正常工作
解决方法: 请确认 @Transactional注解是加在方法上而不是 Service 类上,添加了
@Transactional的方法因为在 Service 层开启了事务,
会在事务结束之后才会切换数据源
检出
DataSourceTransactionManagerBean 注入正确
@Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dynamicDataSource()); }
6. The dependencies of some of the beans in the application context form a cycle
错误信息:The dependencies of some of the beans in the application context form a cycle: produceController (field private cn.com.hellowood.dynamicdatasource.service.ProductService cn.com.hellowood.dynamicdatasource.controller.ProduceController.productService) ↓ productService (field private cn.com.hellowood.dynamicdatasource.mapper.ProductDao cn.com.hellowood.dynamicdatasource.service.ProductService.productDao) ↓ productDao defined in file [/Users/hehuimin/Downloads/Dev/SpringBoot/DynamicDataSource/out/production/classes/cn/com/hellowood/dynamicdatasource/mapper/ProductDao.class] ↓ sqlSessionFactoryBean defined in class path resource [cn/com/hellowood/dynamicdatasource/configuration/DataSourceConfigurer.class] ┌─────┐ | dynamicDataSource defined in class path resource [cn/com/hellowood/dynamicdatasource/configuration/DataSourceConfigurer.class] ↑ ↓ | master defined in class path resource [cn/com/hellowood/dynamicdatasource/configuration/DataSourceConfigurer.class] ↑ ↓ | dataSourceInitializer └─────┘
这是因为在注入
注入的 Bean, 陷入了循环,无法启动项目
解决方法:将 DataSource的实例的时候产生了循环调用,第一个注入的 Bean 依赖于其他的 Bean, 而被依赖的 Bean 产生依赖传递,依赖第一个
注入的 Bean, 陷入了循环,无法启动项目
@Primary注解指向没有依赖的 Bean,如:
/** * master DataSource * @Primary 注解用于标识默认使用的 DataSource Bean,因为有三个 DataSource Bean,该注解可用于 master * 或 slave DataSource Bean, 但不能用于 dynamicDataSource Bean, 否则会产生循环调用 * * @ConfigurationProperties 注解用于从 application.properties 文件中读取配置,为 Bean 设置属性 * @return data source */ @Bean("master") @Primary @ConfigurationProperties(prefix = "application.server.db.master") public DataSource master() { return DataSourceBuilder.create().build(); } @Bean("slave") @ConfigurationProperties(prefix = "application.server.db.slave") public DataSource slave() { return DataSourceBuilder.create().build(); } @Bean("dynamicDataSource") public DataSource dynamicDataSource() { DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource(); Map<Object, Object> dataSourceMap = new HashMap<>(2); dataSourceMap.put("master", master()); dataSourceMap.put("slave", slave()); // Set master datasource as default dynamicRoutingDataSource.setDefaultTargetDataSource(master()); // Set master and slave datasource as target datasource dynamicRoutingDataSource.setTargetDataSources(dataSourceMap); // To put datasource keys into DataSourceContextHolder to judge if the datasource is exist DynamicDataSourceContextHolder.dataSourceKeys.addAll(dataSourceMap.keySet()); return dynamicRoutingDataSource; }
相关文章推荐
- 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法
- MyBatis使用foreach进行批量插入遇到的问题以及解决方法
- 使用elasticsearch遇到的一些问题以及解决方法
- 生产环境使用elasticsearch遇到的一些问题以及解决方法(不断更新)
- Android Studio-—使用OpenCV的配置方法和demo以及开发过程中遇到的问题解决
- 使用Ubuntu遇到的问题以及解决方法(持续更新)
- 生产环境使用elasticsearch遇到的一些问题以及解决方法(不断更新)
- Android Studio 使用中遇到的一些问题以及解决方法
- 使用elasticsearch遇到的一些问题以及解决方法(不断更新)
- 使用MFC过程中遇到的问题以及解决方法(二)
- 使用MFC过程中遇到的问题以及解决方法(一)
- Android Studio-—使用OpenCV的配置方法和demo以及开发过程中遇到的问题解决
- 使用elasticsearch遇到的一些问题以及解决方法
- 数据库sql server安装使用遇到的问题以及解决方法
- 生产环境使用elasticsearch遇到的一些问题以及解决方法(不断更新)
- 使用JDBC连接数据库遇到的问题,以及查找到的解决方法
- 在SharePoint中服务器端使用Word编程模型转换PDF遇到的问题以及解决方法
- 使用CentOS 遇到的问题以及解决方法(持续更新)
- 使用elasticsearch遇到的一些问题以及解决方法(不断更新)
- 使用elasticsearch遇到的一些问题以及解决方法