springboot设置双数据源

该博客详细介绍了如何在Spring Boot项目中配置和使用双数据源,包括 Druid 数据源的配置、AOP 切面注解的实现以及动态数据源的切换。通过创建自定义注解和切面,实现了在不同数据库间动态切换,提高了代码的灵活性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发项目的时候一个项目要访问不同的数据库,所以要用到双数据源

首先配置类:

url 账号密码自行改。我的是两种不同类型的数据库,相同的也是一样的。

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    db:
      jdbc-url: jdbc:postgresql://172.16.20.58:5432/zrzy_gis
      username: ${MYSQL-USER:postgres}
      password: ${MYSQL-PWD:root}
      driver-class-name: org.postgresql.Driver
      hikari:
        maximum-pool-size: 25
        auto-commit: true
        minimum-idle: 5
        idle-timeout: 30000
        pool-name: DatebookHikariCP
        max-lifetime: 1800000
        connection-timeout: 30000
        connection-test-query: select 1
    db2:
      jdbc-url: jdbc:mysql://${MYSQL-HOST:okayx-mysql}:${MYSQL-PORT:3306}/${MYSQL-DB:okayxx_gis_support}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: ${MYSQL-USER:root}
      password: ${MYSQL-PWD:root}

我们用aop实现 ,所以先导入aop的包和aspectj的包

<dependency>
			   <groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
 <version>1.9.6</version>
		</dependency>
 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
      <version>2.3.2.RELEASE</version>
    </dependency>

 我们需要自己加载数据源,所以run方法里面排除数据库加载类


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

数据源加载类,加载两个数据源的配置

/**
 * @Author: ch
 * @Date: 2018/6/27 11:06
 * @Description: 加载数据库配置
 */
@Configuration
public class DataSourceConfig {

	@Bean(name = "db")
	@ConfigurationProperties(prefix = "spring.datasource.db")
	public DataSource dataSource1() {
		return DataSourceBuilder.create().build();
	}

	@Bean(name = "db2")
	@ConfigurationProperties(prefix = "spring.datasource.db2")
	public DataSource dataSource2() {
		return DataSourceBuilder.create().build();
	}

	/**
	 * 动态数据源: 通过AOP在不同数据源之间动态切换
	 *
	 * @return
	 */
	@Primary
	@Bean(name = "dynamicDS1")
	public DataSource dataSource() {
		DynamicDataSource dynamicDataSource = new DynamicDataSource();
		// 默认数据源
		dynamicDataSource.setDefaultTargetDataSource(dataSource1());

		// 配置多数据源
		Map<Object, Object> dsMap = new HashMap(5);
		dsMap.put("db", dataSource1());
		dsMap.put("db2", dataSource2());

		dynamicDataSource.setTargetDataSources(dsMap);
		return dynamicDataSource;
	}
	/**
	 * 配置@Transactional注解事物
	 * @return
	 */
	@Bean
	public PlatformTransactionManager transactionManager() {
		return new DataSourceTransactionManager(dataSource());
	}
}

 设置数据源类

public class DataSourceContextHolder {
	/**
	 * 默认数据源
	 */
	public static final String DEFAULT_DS = "db";

	private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

	// 设置数据源名
	public static void setDB(String dbType) {
		contextHolder.set(dbType);
	}

	// 获取数据源名
	public static String getDB() {
		return (contextHolder.get());
	}

	// 清除数据源名
	public static void clearDB() {
		contextHolder.remove();
	}
}

 获取数据源

/**
 * @Author: ch
 * @Date: 2018/6/27 11:40
 * @Description:
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
	@Override
	protected Object determineCurrentLookupKey() {
		return DataSourceContextHolder.getDB();
	}
}

 aop切面注解,默认db。

/**
 * @Author: ch
 * @Date: 2018/6/27 11:47
 * @Description:
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({
		ElementType.METHOD
})
public @interface DS {
	String value() default "db";
}

 aspect切面类

/**
 * @Author: ch
 * @Date: 2018/6/27 11:48
 * @Description:
 */
@Aspect
@Component
public class DynamicDataSourceAspect {

	@Before("@annotation(DS)")
	public void beforeSwitchDS(JoinPoint point){

		//获得当前访问的class
		Class<?> className = point.getTarget().getClass();

		//获得访问的方法名
		String methodName = point.getSignature().getName();
		//得到方法的参数的类型
		Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
		String dataSource = DataSourceContextHolder.DEFAULT_DS;
		try {
			// 得到访问的方法对象
			Method method = className.getMethod(methodName, argClass);

			// 判断是否存在@DS注解
			if (method.isAnnotationPresent(DS.class)) {
				DS annotation = method.getAnnotation(DS.class);
				// 取出注解中的数据源名
				dataSource = annotation.value();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 切换数据源
		DataSourceContextHolder.setDB(dataSource);

	}


	@After("@annotation(DS)")
	public void afterSwitchDS(JoinPoint point){
		DataSourceContextHolder.clearDB();

	}
}

测试 :只需要在方法上加注解 @DS("db2")就可以切换数据源

 /**
     * 分页查询
     * @param page 分页对象
     * @param gisSupportTest 模型管理
     * @return
     */
    @DS("db2")
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @GetMapping("/page" )
    public R getGisSupportTestPage(Page page, GisSupportTest gisSupportTest) {
        return R.ok(gisSupportTestService.page(page, Wrappers.query(gisSupportTest)));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值