多数据源
第一章 自定义多数据源
文章目录
- 多数据源
- 前言
- 一、先在配置文件中配置好多个数据源
- 二、配置数据源的配置文件
- 三、定义动态数据源配置
- 1、自定义了Datasource,主要目的是为了在Spring容器中定义一个datasource的Bean,用于mybtais获取数据库连接使用。 2、为jdbc获取数据连接 
- 四、自定义注解,用来判断curd,按照不同的操作类型进行区分
- 总结
前言
本案例是使用spring-boot+mysql 来作为案例,需要先搭建好服务。
一、先在配置文件中配置好多个数据源
具体配置示例:
server:port: 8080
spring:datasource:datasource1:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.180.129:13306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: 123456hikari:minimum-idle: 5idle-timeout: 600000maximum-pool-size: 10auto-commit: truepool-name: MyHikariCPmax-lifetime: 1800000connection-timeout: 30000connection-test-query: SELECT 1datasource2:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.180.129:13306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: 123456hikari:minimum-idle: 5idle-timeout: 600000maximum-pool-size: 10auto-commit: truepool-name: MyHikariCPmax-lifetime: 1800000connection-timeout: 30000connection-test-query: SELECT 1
配置了两个数据源,datasource1和datasource2,分别用来表示写与读的数据源
二、配置数据源的配置文件
具体代码示例:
@Configuration
public class DataSourceConfig {@Bean@ConfigurationProperties(prefix = "spring.datasource.datasource1")DataSource dataSource1() {return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.datasource2")DataSource dataSource2() {return DruidDataSourceBuilder.create().build();}
}
1、分别为spring容器定义了两个datasource,同时限定了不同的数据源读取不同的配置
2、具体的限定条件为spring.datasource.datasourcexxxx。
三、定义动态数据源配置
具体代码示例:
@Component
@Primary
public class DynamicDataSource implements DataSource {public static ThreadLocal<OperationTypeEnum> operationType = ThreadLocal.withInitial(() -> OperationTypeEnum.WRITE);@Autowiredprivate DataSource dataSource1;@Autowiredprivate DataSource dataSource2;@Overridepublic Connection getConnection() throws SQLException {OperationTypeEnum operationTypeEnum = operationType.get();switch (operationTypeEnum) {case READ:return dataSource2.getConnection();case WRITE:case DELETE:case UPDATE:return dataSource1.getConnection();}return dataSource1.getConnection();}@Overridepublic Connection getConnection(String username, String password) throws SQLException {OperationTypeEnum operationTypeEnum = operationType.get();switch (operationTypeEnum) {case READ:return dataSource2.getConnection(username, password);case WRITE:case DELETE:case UPDATE:return dataSource1.getConnection(username, password);}return dataSource1.getConnection(username, password);}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}
}
1、自定义了Datasource,主要目的是为了在Spring容器中定义一个datasource的Bean,用于mybtais获取数据库连接使用。
2、为jdbc获取数据连接

四、自定义注解,用来判断curd,按照不同的操作类型进行区分
1、注解的定义
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JdbcOperationAnnotation {OperationTypeEnum value() default OperationTypeEnum.WRITE;
}
2、操作类型枚举的定义
@Getter
public enum OperationTypeEnum {WRITE(0),READ(1),UPDATE(2),DELETE(3);private Integer code;OperationTypeEnum(Integer code) {this.code = code;}
}
3、切面的定义
@Slf4j
@Aspect
@Component
public class JdbcOperationAspect {@Around("@annotation(jdbcOperationAnnotation)")public Object aroundJdbcOperation(ProceedingJoinPoint joinPoint, JdbcOperationAnnotation jdbcOperationAnnotation) throws Throwable {log.info("读取注解信息: {}"+ JSON.toJSONString(jdbcOperationAnnotation));OperationTypeEnum operationTypeEnum = jdbcOperationAnnotation.value();switch (operationTypeEnum) {case READ:DynamicDataSource.operationType.set(OperationTypeEnum.READ);break;case WRITE:DynamicDataSource.operationType.set(OperationTypeEnum.WRITE);break;case UPDATE:DynamicDataSource.operationType.set(OperationTypeEnum.UPDATE);break;case DELETE:DynamicDataSource.operationType.set(OperationTypeEnum.DELETE);}return joinPoint.proceed();}
}
4、注解的使用
@Mapper
public interface UserMapper {@JdbcOperationAnnotation(OperationTypeEnum.READ)@Select("select * from user where username = #{username}")User selectUser(String username);@JdbcOperationAnnotation(OperationTypeEnum.WRITE)@Insert("insert into user(username, password) values (#{username}, #{password})")void addUser(@Param("username") String username, @Param("password") String password);
}
总结
通过重新实现 DataSource 接口,我们可以掌控数据库连接的创建和管理,确保程序按照我们期望的方式执行。这个自定义的过程让我们能够更好地适应特定的业务需求和性能要求,从而优化数据库操作的执行流程。这种灵活性和控制权是自定义数据源的核心优势,让我们能够更好地满足应用程序的需求,确保其稳定性和高效性。