在 SpringBoot 中实现多数据源访问的最佳实践( 二 )

4.5 继承 AbstractRoutingDataSource 抽象类,重写 determineCurrentLookupKey 方法具体如下
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * AbstractRoutingDataSource 在获取 Connection 前会通过 determineTargetDataSource 来从多个数据源中根据 key 来 * * 获取一个 DataSource 对象,这里 determineCurrentLookupKey 由子类来实现 */public class MultiRoutingDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return MultiDataSourceHolder.getDataSource();}}

  • MultiRoutingDataSource 将作为 SqlSessionFactory 和 DataSourceTransactionManager 的数据源
4.6 多数据源配置以及 mybatis 配置
  • MultiDataSourceConfig
import com.ckjava.entity.DbEnum;import com.ckjava.properties.OrderDataSourceProperties;import com.ckjava.properties.UserDataSourceProperties;import com.zaxxer.hikari.HikariDataSource;import org.Apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;import java.util.HashMap;import java.util.Map;@Configuration@EnableTransactionManagement@MapperScan(basePackages = {"com.ckjava.dao"}, sqlSessionFactoryRef = "sqlSessionFactory") // 扫描 Mapper 接口并容器管理public class MultiDataSourceConfig {// 精确到 master 目录,以便跟其他数据源隔离public static final String MAPPER_LOCATION = "classpath:mapper/data/*Mapper.xml";public static final String CONFIG_LOCATION = "classpath:mapper/data/config.xml";@Autowiredprivate UserDataSourceProperties userSourceProperties;@Autowiredprivate OrderDataSourceProperties orderDataSourceProperties;@Bean("userDataSource")public DataSource userDataSource() {HikariDataSource dataSource = DataSourceBuilder.create().driverClassName(userSourceProperties.getDriverClassName()).url(userSourceProperties.getUrl()).username(userSourceProperties.getUsername()).password(userSourceProperties.getPassword()).type(HikariDataSource.class).build();dataSource.setMaximumPoolSize(userSourceProperties.getMaxPoolSize());dataSource.setAutoCommit(true);return dataSource;}@Bean("orderDataSource")public DataSource orderDataSource() {HikariDataSource dataSource = DataSourceBuilder.create().driverClassName(orderDataSourceProperties.getDriverClassName()).url(orderDataSourceProperties.getUrl()).username(orderDataSourceProperties.getUsername()).password(orderDataSourceProperties.getPassword()).type(HikariDataSource.class).build();dataSource.setMaximumPoolSize(orderDataSourceProperties.getMaxPoolSize());dataSource.setAutoCommit(true);return dataSource;}@Bean@Primarypublic DataSource multiRoutingDataSource(@Qualifier("userDataSource") DataSource userDataSource,@Qualifier("orderDataSource") DataSource orderDataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(DbEnum.user, userDataSource);targetDataSources.put(DbEnum.order, orderDataSource);MultiRoutingDataSource myRoutingDataSource = new MultiRoutingDataSource();myRoutingDataSource.setDefaultTargetDataSource(userDataSource);myRoutingDataSource.setTargetDataSources(targetDataSources);return myRoutingDataSource;}@Bean(name = "transactionManager")@Primarypublic PlatformTransactionManager transactionManager(@Qualifier("userDataSource") DataSource userDataSource,@Qualifier("orderDataSource") DataSource orderDataSource) throws Exception {return new DataSourceTransactionManager(multiRoutingDataSource(userDataSource, orderDataSource));}@Bean(name = "sqlSessionFactory")@Primarypublic SqlSessionFactory sqlSessionFactory(@Qualifier("userDataSource") DataSource userDataSource,@Qualifier("orderDataSource") DataSource orderDataSource) throws Exception {final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(multiRoutingDataSource(userDataSource, orderDataSource));sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MultiDataSourceConfig.MAPPER_LOCATION));sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(MultiDataSourceConfig.CONFIG_LOCATION));return sessionFactory.getObject();}}4.7 通过 ThreadLocal 来存储当前线程的 数据库 key 变量


推荐阅读