springboot配置多数据源(静态和动态数据源)
作者:随风丶飘
在开发过程中,很多时候都会有垮数据库操作数据的情况,需要同时配置多套数据源,本文主要介绍了springboot配置多数据源(静态和动态数据源),感兴趣的可以了解一下
背景
在开发过程中,很多时候都会有垮数据库操作数据的情况,需要同时配置多套数据源,即多个数据库,保证不同的业务在不同的数据库执行操作,通过mapper来灵活的切换数据源。
本文以sqlserver和mysql混合数据源配置为例。
配置多数据源方案
1、通过mapper配置数据源
2、配置动态数据源
具体实现
1)、 通过mapper配置数据源
(1)maven配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
(2)服务配置文件,application.yml
server: port: 9900 spring: datasource: db1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc-url: jdbc:sqlserver://localhost:10009;DatabaseName=test username: sa password: 654321 db2: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/test2?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=true username: root password: 123456
(3)添加数据库配置
@Configuration public class DataSourceConfig { @Bean(name = "maindb") @Primary @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource businessDbDataSource() { return new HikariDataSource(); } @Bean(name = "seconddb") @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource newhomeDbDataSource() { return new HikariDataSource(); } }
(4)单独配置每个数据源信息
注意:@Primary该注解理解为默认数据源
包路径配置可对比参考后面的项目结构截图
@Configuration @MapperScan(basePackages = {"com.gxin.datasource.dao.maindb"}, sqlSessionFactoryRef = "sqlSessionFactoryMaindb") public class DatasourceMainConfig { @Autowired @Qualifier("maindb") private DataSource dataSourceMaindb; @Bean @Primary public SqlSessionFactory sqlSessionFactoryMaindb() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSourceMaindb); factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/maindb/*.xml")); // 打印sql日志 // org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); // configuration.setLogImpl(StdOutImpl.class); // factoryBean.setConfiguration(configuration); return factoryBean.getObject(); } @Bean @Primary public SqlSessionTemplate sqlSessionTemplateMaindb() throws Exception { return new SqlSessionTemplate(sqlSessionFactoryMaindb()); } }
@Configuration @MapperScan(basePackages = {"com.gxin.datasource.dao.seconddb"}, sqlSessionFactoryRef = "sqlSessionFactorySeconddb") public class DatasourceSecondConfig { @Autowired @Qualifier("seconddb") private DataSource dataSourceSeconddb; @Bean public SqlSessionFactory sqlSessionFactorySeconddb() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSourceSeconddb); factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/seconddb/*.xml")); // 打印sql日志 // org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); // configuration.setLogImpl(StdOutImpl.class); // factoryBean.setConfiguration(configuration); return factoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplateSeconddb() throws Exception { return new SqlSessionTemplate(sqlSessionFactorySeconddb()); } }
(5)根据每个单独的数据源的配置信息搭建mapper接口和mapper.xml文件
(6)配置mapper多数据源完成,下图为完整的项目结构
2)、 配置动态数据源
(1)maven配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
(2)服务配置文件,application.yml
server: port: 9901 spring: main: allow-bean-definition-overriding: true datasource: db1: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc-url: jdbc:sqlserver://localhost:10009;DatabaseName=test username: sa password: 654321 db2: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/test2?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=true username: root password: 123456
(3)添加数据源列表
public interface DataSourceConstant { /** * 默认数据库 */ String MAIN = "MAIN"; /** * 第二数据库 */ String SECOND = "SECOND"; }
(4)动态数据源数据库信息配置
@Configuration @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) public class DynamicDataSourceConfig { // 核心数据库 @Bean(name = DataSourceConstant.MAIN) @ConfigurationProperties(prefix = "spring.datasource.db1") public DataSource getMAINDataSource() { return new HikariDataSource(); } // 第二数据库 @Bean(name = DataSourceConstant.SECOND) @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource getSECONDDataSource() { return new HikariDataSource(); } @Bean @Primary public DataSource dynamicDataSource() { Map<Object, Object> dataSourceMap = new HashMap<>(); dataSourceMap.put(DataSourceConstant.MAIN, getMAINDataSource()); dataSourceMap.put(DataSourceConstant.SECOND, getSECONDDataSource()); //设置动态数据源 DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setTargetDataSources(dataSourceMap); dynamicDataSource.setDefaultTargetDataSource(getMAINDataSource()); return dynamicDataSource; } }
(5)添加动态数据源策略获取配置,继承AbstractRoutingDataSource
@Component public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // 此处暂时返回固定 master 数据源, 后面按动态策略修改 return DynamicDataSourceContextHolder.getContextKey(); } }
(6)数据源切换策略配置
public class DynamicDataSourceContextHolder { /** * 动态数据源名称上下文 */ private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>(); /** * 设置/切换数据源 */ public static void setContextKey(String key) { DATASOURCE_CONTEXT_KEY_HOLDER.set(key); } /** * 获取数据源名称 */ public static String getContextKey() { String key = DATASOURCE_CONTEXT_KEY_HOLDER.get(); return key == null ? DataSourceConstant.MAIN : key; } /** * 删除当前数据源名称 */ public static void removeContextKey() { DATASOURCE_CONTEXT_KEY_HOLDER.remove(); } }
(6.1) 这里写掉了,补充数据库会话配置
@Configuration public class SqlSessionConfig { @Autowired private DynamicDataSource source; public SqlSessionConfig() { } @Bean(name = {"sqlSessionFactoryBean"}) public SqlSessionFactoryBean getSessionFactory() throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(this.source); factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")); // 打印sql日志 org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setLogImpl(StdOutImpl.class); factory.setConfiguration(configuration); return factory; } @Bean(name = {"sqlSession"}) public SqlSessionTemplate getSqlSession() throws Exception { return new SqlSessionTemplate(Objects.requireNonNull(getSessionFactory().getObject())); // SqlSessionFactory factory = this.getSessionFactory().getObject(); // return new SqlSessionTemplate(factory, ExecutorType.BATCH); } @Bean public DataSourceTransactionManager getDataSourceTransaction() { DataSourceTransactionManager manager = new DataSourceTransactionManager(); manager.setDataSource(this.source); return manager; } }
(7) 添加切换数据源标识注解,默认为MAIN数据源
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DBS { /** * 数据源名称 */ String value() default DataSourceConstant.MAIN; }
(8)通过配置的数据源标识注解,动态切换数据源
@Aspect @Component public class DynamicDataSourceAspect { @Pointcut("@annotation(com.gxin.dynamicdatasource.config.DBS)") public void dataSourcePointCut() { } @Around("dataSourcePointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { String dsKey = getDSAnnotation(joinPoint).value(); DynamicDataSourceContextHolder.setContextKey(dsKey); try { return joinPoint.proceed(); } finally { DynamicDataSourceContextHolder.removeContextKey(); } } /** * 根据类或方法获取数据源注解 */ private DBS getDSAnnotation(ProceedingJoinPoint joinPoint) { Class<?> targetClass = joinPoint.getTarget().getClass(); DBS dsAnnotation = targetClass.getAnnotation(DBS.class); // 先判断类的注解,再判断方法注解 if (Objects.nonNull(dsAnnotation)) { return dsAnnotation; } else { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); return methodSignature.getMethod().getAnnotation(DBS.class); } } }
(9)到此动态数据源配置完成,一下的为使用情况,需要使用哪个数据源添加注解配置即可
@Repository public interface TestMapper { int getModelcount(); @DBS(DataSourceConstant.SECOND) int getUsercount(); }
(10)service层
@Service public class ServiceInfo { @Autowired private TestMapper mainMapper; public void datasource() { int modelcount = mainMapper.getModelcount(); System.out.println(modelcount); int usercount = mainMapper.getUsercount(); System.out.println(usercount); } }
(11)mapper. xml结构目录
(12)完整的项目结构截图
到此这篇关于springboot配置多数据源(静态和动态数据源)的文章就介绍到这了,更多相关springboot 多数据源内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- SpringBoot动态数据源连接测试的操作详解
- SpringBoot实现动态数据源切换的方法总结
- SpringBoot中动态数据源是实现与用途
- Springboot实现根据用户ID切换动态数据源
- 如何在Java SpringBoot项目中配置动态数据源你知道吗
- 详解SpringBoot+Mybatis实现动态数据源切换
- SpringBoot Mybatis动态数据源切换方案实现过程
- 通过springboot+mybatis+druid配置动态数据源
- SpringBoot整合MyBatisPlus配置动态数据源的方法
- springboot 动态数据源的实现方法(Mybatis+Druid)
- SpringBoot实现动态数据源切换的项目实践