Issues and workarounds for dynamically switching data sources using Spring Boot and MyBatis

Source: Internet
Author: User
Tags addall

Related Project address: Https://github.com/helloworlde/SpringBoot-DynamicDataSource

1. Org.apache.ibatis.binding.BindingException:Invalid bound statement (not found)

The problem was encountered after using the dynamic Data source, which was caused by the failure to find the *.xml file, but in the configuration file
It is true that the related configuration was added because it was not set after setting SqlSessionFactoryBean the typeAliasesPackage data source.
and mapperLocations property or property is invalid;

    • Workaround:

If you added it in the application's entry class @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) ,
DataSourceConfigureset the related property in the class:

    @Bean    @ConfigurationProperties"mybatis")
publicsqlSessionFactoryBean() {
new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
return sqlSessionFactoryBean;
}

or direct configuration (this is not recommended):

  @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 I Dentify The bean that should is consumed

The exception is clearly stated in the error message because there are multiple DataSource instances, so it is not possible to determine the reference to that instance

    • Workaround:

To add an annotation to a data source Bean @Primary , it Bean should be DataSourceBuilder.create().build()
The resulting Bean , rather than new AbstractRoutingDataSource the subclass of the implementation Bean , in this project can be master()
Or slave() get DataSource , can't be dynamicDataSource() got.DataSource

3. Dynamic switch data source is invalid by annotation mode
    • Make sure that the annotations are not placed on the DAO layer method because transactions are turned on at the service layer, so the annotations do not take effect when they are in the DAO layer
    • Please confirm the following Bean correct configuration:
    @Bean("Dynamicdatasource")
PublicDataSourceDynamicdatasource() {
Dynamicroutingdatasource Dynamicroutingdatasource =NewDynamicroutingdatasource ();
Map<object, object> datasourcemap =NewHashmap<> (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 ());
}
returnDynamicroutingdatasource;
}
@Bean
@ConfigurationProperties(prefix ="MyBatis")
PublicSqlsessionfactorybeanSqlsessionfactorybean() {
Sqlsessionfactorybean Sqlsessionfactorybean =NewSqlsessionfactorybean ();
//Here's very important, if don ' t config this, would can ' t switch datasource
//Put all DataSource to Sqlsessionfactorybean, then'll autoconfig sqlsessionfactory
Sqlsessionfactorybean.setdatasource (Dynamicdatasource ());
returnSqlsessionfactorybean;
}
4. @Transactionalinvalid annotation, exception not rolled back
    • Verify that it is Bean properly configured and @Transactional rollbackFor configured correctly
    @Bean
publictransactionManager() {
returnnew DataSourceTransactionManager(dynamicDataSource());
}
5. Invalid switch data source when DAO layer method name is judged by AOP

After the slice points to the DAO layer, regardless of the order in which the slices are set, the data source cannot be toggled before the query is executed, but the slice changes to the Service layer and works correctly

    • Workaround: Make sure that the @Transactional annotations are added to the method instead of the service class, @Transactional because transactions are turned on in the service layer.
      The data source will not be switched until after the transaction has ended

    • Check out DataSourceTransactionManager beans injected correctly

    @Bean
publictransactionManager() {
returnnew DataSourceTransactionManager(dynamicDataSource());
}
6. The dependencies of some of the beans in the application context form a cycle
    • Error message:
The dependencies of some of the beansinchThe application context form a cycle:
Producecontroller (Field private CN. com. Hellowood. Dynamicdatasource. Service. Productservicecn. com. Hellowood. Dynamicdatasource. Controller. Producecontroller. Productservice)

Productservice (Field private CN. com. Hellowood. Dynamicdatasource. Mapper. Productdaocn. com. Hellowood. Dynamicdatasource. Service. Productservice. Productdao)

Productdao definedinchfile [/users/hehuimin/downloads/dev/springboot/dynamicdatasource/ out/production/classes/cn/com/hellowood/dynamicdatasource/mapper/productdao. Class]

Sqlsessionfactorybean definedinchClass path Resource [cn/com/hellowood/dynamicdatasource/configuration/datasourceconfigurer. Class]
┌─────┐
| Dynamicdatasource definedinchClass path Resource [cn/com/hellowood/dynamicdatasource/configuration/datasourceconfigurer. Class]


| Master definedinchClass path Resource [cn/com/hellowood/dynamicdatasource/configuration/datasourceconfigurer. Class]


| Datasourceinitializer
└─────┘

This is because the injected DataSource instance produces a cyclic call, and the first injected bean relies on the other bean, and the dependent bean generates a dependency pass, relying on the first
Injected beans, caught in a loop, unable to start the project

    • Workaround: Point the @Primary annotation to a Bean that is not dependent, such as:
    /**
* Master DataSource
* @Primary annotations are used to identify the DataSource bean that is used by default because there are three DataSource beans that can be used with the master
* or slave DataSource bean, but not for dynamicdatasource bean, otherwise it will produce a cyclic call
* * @ConfigurationProperties annotations are used to read the configuration from the Application.properties file and to set properties for the Bean
* @return Data source
*/
@Bean("Master")
@Primary
@ConfigurationProperties(prefix ="Application.server.db.master")
PublicDataSourceMaster() {
returnDatasourcebuilder.create (). build ();

}@Bean("Slave")
@ConfigurationProperties(prefix ="Application.server.db.slave")
PublicDataSourceslave() {
returnDatasourcebuilder.create (). build ();

}@Bean("Dynamicdatasource")
PublicDataSourceDynamicdatasource() {
Dynamicroutingdatasource Dynamicroutingdatasource =NewDynamicroutingdatasource ();
Map<object, object> datasourcemap =NewHashmap<> (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 ());
returnDynamicroutingdatasource;

}

Issues and workarounds for dynamically switching data sources using Spring Boot and MyBatis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.