Spring Boot + Mybatis multi-data source and dynamic data source configuration method, mybatis Dynamic Data

Source: Internet
Author: User

Spring Boot + Mybatis multi-data source and dynamic data source configuration method, mybatis Dynamic Data

The articles on the Internet basically only have multiple data sources or only dynamic data sources. The latest projects need to use two methods at the same time. Record the configuration methods for your reference.

Application scenarios

The project needs to connect two different databases A and B at the same time, and they are both master-slave architecture, one write database and multiple read databases.

Multiple Data sources

First, disable the DataSourceAutoConfiguration that comes with spring boot because it will read the spring. datasource. * attribute of the application. properties file and automatically configure a single data source. Add the exclude attribute to the @ SpringBootApplication annotation:

@SpringBootApplication(exclude = {  DataSourceAutoConfiguration.class})public class TitanWebApplication { public static void main(String[] args) {  SpringApplication.run(TitanWebApplication.class, args); }}

Then configure the multi-data source connection information in application. properties:

# Titan library spring. datasource. titan-master.url = jdbc: mysql: // X. X: port/titan? CharacterEncoding = UTF-8spring.datasource.titan-master.username = spring. datasource. titan-master.password = spring. datasource. titan-master.driver-class-name = com. mysql. jdbc. driver # connection pool configuration # omitted # other libraries spring. datasource. db2.url = jdbc: mysql: // X. x. x. x: port/titan2? CharacterEncoding = UTF-8spring.datasource.db2.username = spring. datasource. db2.password = spring. datasource. db2.driver-class-name = com. mysql. jdbc. Driver

Because automatic data source configuration is disabled, You need to manually create these data sources in the next step:

@ Configurationpublic class performanceconfig {@ Bean (name = "titanMasterDS") @ ConfigurationProperties (prefix = "spring. datasource. titan-master ") // application. the prefix of the attribute in properteis public DataSource performance1 () {return performancebuilder. create (). build () ;}@ Bean (name = "ds2") @ ConfigurationProperties (prefix = "spring. datasource. db2 ") // application. the prefix of the attribute in properteis public DataSource performance2 () {return performancebuilder. create (). build ();}}

Next, you need to configure two SqlSessionFactory mybatis to use different data sources:

@ Configuration @ MapperScan (basePackages = {"titan. mapper "}, sqlSessionFactoryRef =" sqlSessionFactory1 ") public class MybatisDbAConfig {@ Autowired @ Qualifier (" titanMasterDS ") private DataSource ds1; @ Bean public SqlSessionFactory sqlSessionFactory1 () throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean (); factoryBean. setDataSource (ds1); // use the titan data source to connect to the titan library return factoryBean. getObject () ;}@ Bean public SqlSessionTemplate sqlSessionTemplate1 () throws Exception {SqlSessionTemplate template = new SqlSessionTemplate (sqlSessionFactory1 (); // use the Factory return template configured above ;}}

After the above configuration, the mapper interface under titan. Mapper will use the titan data source. Likewise, you can configure the second SqlSessionFactory:

@Configuration@MapperScan(basePackages = {"other.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory2")public class MybatisDbBConfig { @Autowired @Qualifier("ds2") private DataSource ds2; @Bean public SqlSessionFactory sqlSessionFactory2() throws Exception {  SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();  factoryBean.setDataSource(ds2);  return factoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate2() throws Exception {  SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory2());  return template; }}

After completing these configurations, assume that there are two Mapper titan. mapper. UserMapper AND other. mapper. RoleMapper. The former will automatically connect to the titan library, and the latter will connect to the ds2 library.

Dynamic Data Source

The original intention of using dynamic data sources is to achieve read/write separation at the application layer, that is, to control different query methods in program code to connect different databases. In addition to this method, database middleware is also a good choice. It has the advantage that the database cluster only exposes a single database for applications and does not need to switch the code logic of the data source.

We use custom annotations + AOP to implement dynamic data source switching.

First, define a ContextHolder to save the name of the data source used by the current thread:

Public class performancecontextholder {public static final Logger log = LoggerFactory. getLogger (performancecontextholder. class);/*** default data source */public static final String DEFAULT_DS = "titan-master"; private static final ThreadLocal <String> contextHolder = new ThreadLocal <> (); // set the data source name public static void setDB (String dbType) {log. debug ("switch to {} data source", dbType); contextHolder. set (dbType);} // obtain the data source name public static String getDB () {return (contextHolder. get ();} // clear the data source name public static void clearDB () {contextHolder. remove ();}}

Then, you can customize the implementation of a javax. SQL. DataSource interface. Here, you only need to inherit the parent class that Spring has implemented in advance to actroutingdatasource:

Public class DynamicDataSource extends actroutingdatasource {private static final Logger log = LoggerFactory. getLogger (DynamicDataSource. class); @ Override protected Object determineCurrentLookupKey () {log. debug ("Data source: {}", performancecontextholder. getDB (); return DataSourceContextHolder. getDB ();}}

Create a Dynamic Data source:

/*** Dynamic Data source: Use AOP to dynamically switch between different data sources * @ return */@ Bean (name = "dynamicDS1") public DataSource dataSource () {DynamicDataSource dynamicDataSource = new DynamicDataSource (); // default data source dynamicDataSource. setDefaultTargetDataSource (performance1 (); // configure multi-data source Map <Object, Object> dsMap = new HashMap (5); dsMap. put ("titan-master", performance1 (); dsMap. put ("ds2", performance2 (); dynamicDataSource. setTargetDataSources (dsMap); return dynamicDataSource ;}

Custom annotation @ DS is used to specify the data source used by the method during encoding:

@Retention(RetentionPolicy.RUNTIME)@Target({  ElementType.METHOD})public @interface DS { String value() default "titan-master";}

Write the AOP aspect to implement the switching logic:

@ Aspect @ Componentpublic class DynamicDataSourceAspect {@ Before ("@ annotation (DS)") public void beforeSwitchDS (JoinPoint point) {// obtain the currently accessed class <?> ClassName = point. getTarget (). getClass (); // method name for access String methodName = point. getSignature (). getName (); // type of the obtained method parameter Class [] argClass = (MethodSignature) point. getSignature ()). getParameterTypes (); String dataSource = performancecontextholder. DEFAULT_DS; try {// Method object for access method = className. getMethod (methodName, argClass); // determine whether @ DS annotation if (method. isAnnotationPresent (DS. class) {DS annotation = method. getAnnotation (DS. class); // retrieve the data source name dataSource = annotation in the annotation. value () ;}} catch (Exception e) {e. printStackTrace ();} // switch the data source cececontextholder. setDB (dataSource) ;}@ After ("@ annotation (DS)") public void afterSwitchDS (JoinPoint point) {performancecontextholder. clearDB ();}}

After completing the preceding configuration, specify DynamicDataSource in the previous SqlSessionFactory configuration to switch the data source happily in the Service:

@Autowired private UserAModelMapper userAMapper; @DS("titan-master") public String ds1() {  return userAMapper.selectByPrimaryKey(1).getName(); } @DS("ds2") public String ds2() {  return userAMapper.selectByPrimaryKey(1).getName(); }

Summary

The above is a small series of Spring Boot + Mybatis multi-data source and dynamic data source configuration methods, I hope to help you, if you have any questions, please leave a message, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!

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.