Springboot整合mybatis配置多数据源
1.自定义动态数据源类继承AbstractRoutingDataSouce类,并创建一个ThreadLocal变量,用于设置或者获取当前数据源的key
2.实现determineCurrentLookupKey()方法,此方法用于确定当前数据源的key,以选择对应的数据源。
3.将多数据源封装到targetDataSources对象中,并指定默认数据源
4.将自定义数据源绑定到SqlSessionFactoryBean实例上;
5.自定义切面对需要的方法进行拦截,并设置数据源的key
具体相关示例代码如下:
1 public class DynamicDataSource extends AbstractRoutingDataSource { 2 3 public static final String DB1_DATA_SOURCE = "db1DataSource"; 4 public static final String DB2_DATA_SOURCE = "db2DataSource"; 5 6 private static final ThreadLocal<String> CURRENT_DATA_SOURCE = new ThreadLocal<>(); 7 8 /** 9 * 设置当前数据源 10 * @param dataSourceName 11 */ 12 public static void setDataSource(String dataSourceName) { 13 CURRENT_DATA_SOURCE.set(dataSourceName); 14 } 15 16 public static String getDataSource(){ 17 return CURRENT_DATA_SOURCE.get(); 18 } 19 @Override 20 protected Object determineCurrentLookupKey() { 21 String dataSource = CURRENT_DATA_SOURCE.get(); 22 if(StringUtils.isEmpty(dataSource)){ 23 return DB1_DATA_SOURCE; 24 } 25 return dataSource; 26 } 27 }
1 @Bean 2 public DynamicDataSource dataSource( 3 @Qualifier(DynamicDataSource.DB1_DATA_SOURCE) DataSource db1DataSource, 4 @Qualifier(DynamicDataSource.DB2_DATA_SOURCE) DataSource db2DataSource){ 5 6 // logger.info("配置动态数据源:db1DataSource:{},db2DataSource:{}",db1DataSource,db2DataSource); 7 DynamicDataSource dynamicDataSource = new DynamicDataSource(); 8 Map<Object,Object> targetDataSources = new HashMap<>(); 9 targetDataSources.put(DynamicDataSource.DB1_DATA_SOURCE,db1DataSource); 10 targetDataSources.put(DynamicDataSource.DB2_DATA_SOURCE,db2DataSource); 11 dynamicDataSource.setDefaultTargetDataSource(db1DataSource); 12 dynamicDataSource.setTargetDataSources(targetDataSources); 13 dynamicDataSource.afterPropertiesSet(); 14 return dynamicDataSource; 15 } 16 17 @Bean 18 public SqlSessionFactoryBean sqlSessionFactoryBean(DynamicDataSource dynamicDataSource) throws IOException { 19 logger.info("配置SqlSessionFactoryBean:{}",dynamicDataSource.determineCurrentLookupKey()); 20 SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); 21 org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); 22 configuration.setLogImpl(StdOutImpl.class); 23 configuration.setMapUnderscoreToCamelCase(true); 24 configuration.setCallSettersOnNulls(true); 25 sqlSessionFactoryBean.setConfiguration(configuration); 26 sqlSessionFactoryBean.setDataSource(dynamicDataSource); 27 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 28 sqlSessionFactoryBean.setMapperLocations(resolver.getResources(mapperLocations)); 29 return sqlSessionFactoryBean; 30 }
如果多数据源中如果除了纯db连接配置还有JNDI的数据源,可以对数据源做如下处理
1 @Primary 2 @Bean(name = DynamicDataSource.DB1_DATA_SOURCE) 3 @ConfigurationProperties(prefix = DB1_DATA_SOURCE_PREFIX) 4 public DataSource db1DataSource() throws NamingException { 5 String jndiName = jndi1DataSource.getJndiName(); 6 if (!StringUtils.isEmpty(jndiName)){ 7 logger.info("db1DataSource使用的JNDI数据源"); 8 return jndiDataSource(jndiName); 9 } 10 return DataSourceBuilder.create().build(); 11 }
如果不需要做动态数据源,而是固定多数据源的情况,直接配置两个sqlSessionFactory,每个SqlSessionFactory指定自己的配置,代码示例如下:
@Configuration @Slf4j @MapperScan(basePackages = "com.xxx.xxx.dao.xxx",sqlSessionFactoryRef = "sqlSessionFactory2") public class DataSourceConfig { @Value("${mybatis.mapper-locations}") private String mapperLocations; @Bean(name = "db2DataSource") @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource db2DataSource(){ return DataSourceBuilder.create().build(); } @Bean public DataSourceTransactionManager transactionManager2(DataSource db2DataSource){ return new DataSourceTransactionManager(db2DataSource); } @Bean public SqlSessionFactory sqlSessionFactory2(DataSource db2DataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setLogImpl(StdOutImpl.class); configuration.setMapUnderscoreToCamelCase(true); configuration.setCallSettersOnNulls(true); sqlSessionFactoryBean.setConfiguration(configuration); sqlSessionFactoryBean.setDataSource(db2DataSource); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources(mapperLocations)); return sqlSessionFactoryBean.getObject(); } }
注:以上方式可以保证不同数据源拥有自己的事务管理器,如果是动态数据源,即使配置多个事务管理器也不生效。
探索不以困难而止,学习不以艰苦而终

浙公网安备 33010602011771号