SpringBoot项目实现多数据源的三种方式

在开发过程中,我们经常被要求在一个项目中使用多数据源下面是总结下,使用多数据源的几种方式:

方式一:在同一实例下的不同数据库(在写SQL的时候用(数据库名称+"."+表名))

方式二:AOP+注解实多数据源

方式三:使用dynamic-datasource-spring-boot-starter实现多数据源

方式一:不用对程序做任何更改,只是写SQL时加上表名称

上面是在同一实例下面的不同数据库(citex_guess,citex_fusion),我先在一个项目中同时操作这两个数据库怎么半办啦!


select  * from  citex_fusion.fusion_invitee limit 10
select  * from  citex_guess.guess_account limit 10

不论是增删改查,只要是对数据库表进行操作,都需要加上表名

方式二、三、四通用实体类,mapper,service、web层

@Data
public class GuessAccount {
	private Long id;
	private Integer userId;
	private Integer currencyId;
	private String currency;
	private BigDecimal availableQty;
	private BigDecimal frozenQty;
	private Date createTime;
	private Date updateTime;
}
@Data
public class FusionInvite {
	private Integer userId;
	private Integer inviteeId;
	private String code;
	private Date createTime;
	private Date updateTime;
	
}

Mapper代码

@Mapper
public interface FusionMapper {
	@DS("master")
	@Select("select  * from  fusion_invitee limit 10 ")
	List<FusionInvite> getFusionInviteList();

}
@Mapper
public interface GuessMapper {
	@DS("slaveOne")
    @Select("select  * from  guess_account limit 10")
	List<GuessAccount> getGuessAccountList();
	

}

service层

@Service
public class TestService {
	@Autowired
	private FusionMapper fusionMapper;
	
	@Autowired
	private GuessMapper guessMapper;
	
	public  Object  testDynamic() {
		List<FusionInvite> fusionInviteList = getFusionInviteList();
		List<GuessAccount> guessAccountList = getGuessAccountList();
		ResultVos resultVos = new ResultVos();
		resultVos.setFusionList(fusionInviteList);
		resultVos.setGuessList(guessAccountList);
	    return resultVos;	
	}
	
	public List<FusionInvite> getFusionInviteList(){
		List<FusionInvite> fusionList= fusionMapper.getFusionInviteList();
		return fusionList;
	}

	
	public List<GuessAccount> getGuessAccountList(){
		List<GuessAccount> guessList=guessMapper.getGuessAccountList();
		return guessList;
	}

web层

@RestController
public class TestController {
	@Autowired
	private TestService testService;
	
	@PostMapping("getList")
	public  Object  getTestList() {
		return testService.testDynamic();
	}
}

方式二:

Maven依赖:

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.0.BUILD-SNAPSHOT</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>study_demo2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>study_demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
		   <groupId>org.projectlombok</groupId>
		   <artifactId>lombok</artifactId>
		   <scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		 <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        
		<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>druid-spring-boot-starter</artifactId>
		    <version>1.1.8</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
		    <groupId>org.aspectj</groupId>
		    <artifactId>aspectjweaver</artifactId>
		</dependency>
	</dependencies>

配置文件YML

server:
  port: 8025
  
spring:
  application:
        name: study_demo2
  datasource:
     master:
          username: jack
          password: jack987
          driver-class-name: com.mysql.jdbc.Driver
          jdbc-url: jdbc:mysql://127.0.0.1:3306/citex_fusion?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTC
     slave1:
         username: jack
         password: jack987
         driver-class-name: com.mysql.jdbc.Driver
         jdbc-url: jdbc:mysql://127.0.0.1:3306/citex_guess?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTC
     druid:
        initial-size: 5
        max-active: 20
        min-idle: 5
        test-on-borrow: true
        max-wait: -1
        min-evictable-idle-time-millis: 30000
        max-evictable-idle-time-millis: 30000
        time-between-eviction-runs-millis: 0   
mybatis:
  configuration:
    map-underscore-to-camel-case: true

多数据源配置类:

数据源切换注解类:

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

}

动态数据源配置类:

@Configuration
public class DynamicDataSourceConfiguration {
	@Primary
	@Bean(name = "master")
	@ConfigurationProperties(prefix = "spring.datasource.master")
	public DataSource masterDataSource() {
		  DataSource ds = DataSourceBuilder.create().build();
	      return ds;
	}
	
	@Bean(name = "slaveOne")
	@ConfigurationProperties(prefix = "spring.datasource.slave1")
	public DataSource slave_1_DataSource() {
		  DataSource ds = DataSourceBuilder.create().build();
	      return ds;
	}
	
	 /**
     * 动态数据源: 通过AOP在不同数据源之间动态切换
     *
     * @return
     */
    @Bean(name = "dynamicDataSource")
    public DataSource dataSource(@Autowired @Qualifier("master") DataSource primery, @Autowired @Qualifier("slaveOne") DataSource coocon) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默认数据源
        dynamicDataSource.setDefaultTargetDataSource(primery);

        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap<Object, Object>(2);
        dsMap.put("master", primery);
        dsMap.put("slaveOne", coocon);
        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }
    
    
    @Bean
    public PlatformTransactionManager txManager(DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

    @Bean
    @ConfigurationProperties(prefix = "mybatis")
    public SqlSessionFactoryBean sqlSessionFactoryBean(@Autowired @Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        return sqlSessionFactoryBean;
    }


}

实现多数据源的核心类(可动态路由的数据源类型)

public class DynamicDataSource extends AbstractRoutingDataSource {

	public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
 
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDateSoureType();
    }

    public DynamicDataSource() {
		// TODO Auto-generated constructor stub
	}
}

使用ThreadLocal维护数据源类

@Slf4j
public class DynamicDataSourceContextHolder { 
    /**
     * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
     * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
     */
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
 
    /**
     * 设置数据源的变量
     */
    public static void setDateSoureType(String dsType) {
        log.info("切换到{}数据源", dsType);
        CONTEXT_HOLDER.set(dsType);
    }
 
    /**
     * 获得数据源的变量
     */
    public static String getDateSoureType() {
        return CONTEXT_HOLDER.get();
    }
 
    /**
     * 清空数据源变量
     */
    public static void clearDateSoureType() {
        CONTEXT_HOLDER.remove();
    }

}

切面拦截注解实现多数据源切换

@Aspect
@Component
@Slf4j
public class DataSourceAspect {
	
	@Pointcut("@annotation(com.example.study.config.DS)")
	public void dataSourcePointCut() {
		
	}
	
	@Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        DS annotation = method.getAnnotation(DS.class);
        DynamicDataSourceContextHolder.setDateSoureType(annotation.value());
        try {
            return point.proceed();
        } finally {
            // 销毁数据源 在执行方法之后
            log.info("销毁数据源{}", annotation.value());
            DynamicDataSourceContextHolder.clearDateSoureType();
        }
    }
	   

}

以上是通过AOP切换数据源的配置类:

使用通用以上通用的实体类,Mapper、Service、web层便可以实现多数据源的使用。

方式三:使用dynamic-datasource-spring-boot-starter实现多数据源

maven依赖:

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.0.BUILD-SNAPSHOT</version>
		<relativePath/> <!-- lookup parent from repository -->
</parent>




<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
		    <groupId>com.baomidou</groupId>
		    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
		    <version>2.3.2</version>
		</dependency>
		 <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        
		<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>druid-spring-boot-starter</artifactId>
		    <version>1.1.8</version>
		</dependency>

配置文件(yml)

spring:
  application:
        name: study_demo
  datasource:
    dynamic:
      druid:
        initial-size: 5
        max-active: 20
        min-idle: 5
        test-on-borrow: true
        max-wait: -1
        min-evictable-idle-time-millis: 30000
        max-evictable-idle-time-millis: 30000
        time-between-eviction-runs-millis: 0
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      datasource:
        master:
          username: jack
          password: jack987
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/citex_fusion?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTC
        slaveOne:
         username: jack
         password: jack987
         driver-class-name: com.mysql.jdbc.Driver
         url: jdbc:mysql://127.0.0.1:3306/citex_guess?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&serverTimezone=UTC
mybatis:
  configuration:
    map-underscore-to-camel-case: true

测试地址:localhost:8080/getList

结果:

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Spring Boot项目中配置多个数据可以通过以下步骤实现: 1. 禁用Spring Boot的数据自动配置类。在@SpringBootApplication注解中添加exclude属性,值为DataSourceAutoConfiguration.class,如下所示: ```java @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class DatasourceDomeApplication { public static void main(String[] args) { SpringApplication.run(DatasourceDomeApplication.class, args); } } ``` 2. 创建自定义的数据配置类。在该类中使用@Configuration注解,并定义多个@Bean方法,每个方法返回一个DataSource对象,用于初始化不同的数据。可以使用@ConfigurationProperties(prefix = "spring.datasource.mysql-datasourceX")注解来指定每个数据的属性配置,如下所示: ```java @Configuration public class DataSourceConfig { @Bean(name = "mysqlDataSource1") @ConfigurationProperties(prefix = "spring.datasource.mysql-datasource1") public DataSource dataSource1(){ DruidDataSource build = DruidDataSourceBuilder.create().build(); return build; } @Bean(name = "mysqlDataSource2") @ConfigurationProperties(prefix = "spring.datasource.mysql-datasource2") public DataSource dataSource2(){ DruidDataSource build = DruidDataSourceBuilder.create().build(); return build; } } ``` 3. 在application.yml配置文件中配置数据相关的属性。可以根据需要配置每个数据的连接信息、用户名、密码等,如下所示: ```yaml spring: datasource: mysql-datasource1: url: jdbc:mysql://localhost:3306/db1 username: root password: password1 mysql-datasource2: url: jdbc:mysql://localhost:3306/db2 username: root password: password2 ``` 通过以上步骤,你可以成功配置多个数据,并在项目中使用对应的数据进行数据库操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Spring Boot配置多数据的四种方式](https://blog.csdn.net/qq_45515182/article/details/126330084)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [SpringBoot数据配置](https://blog.csdn.net/u012060033/article/details/123759694)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值