背景 :数据同步项目,将接口返回的数据通过定时任务,将数据存储到数据库A,数据库经过一定的清理,生成标准化的数据存在数据库B,再将数据库B数据封装成接口对外开放。
同步工具和对外开放的接口在同一个项目,读写库A、B就是多数据源。
1.pom.xml依赖的包
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-jdbc
provided
com.alibaba
druid-spring-boot-starter
1.1.10
org.springframework.boot
spring-boot-starter-aop
net.minidev
json-smart
2.3
compile
数据配置文件
spring:
application:
name: server
main:
allow-bean-definition-overriding: true
datasource:
hikari:
minimum-idle: 6
maximum-pool-size: 30
connection-timeout: 30000
write:
jdbc-url: jdbc:oracle:thin:@localhost:1521:orcl
username: ods
password: 123456
driver-class-name: oracle.jdbc.driver.OracleDriver
read:
jdbc-url: jdbc:oracle:thin:@localhost:1521:orcl
username: dw
password: 123456
driver-class-name: oracle.jdbc.driver.OracleDriver
jpa:
show-sql: true
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.Oracle10gDialect
hbm2ddl:
auto: none
2.加载配置文件中的数据库
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@EnableTransactionManagement
@Configuration
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class DataSourceConfig {
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.write")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.read")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean
public DynamicRoutingDataSource dynamicDataSource(
@Qualifier(value = "masterDataSource") DataSource masterDataSource,
@Qualifier(value = "slaveDataSource") DataSource slaveDataSource) {
Map
3.数据源类型
public interface DataSourceEnum {
String master = "write";
String slave = "read";
}
4.加载数据库配置
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
Object lookupKey = DynamicRoutingDataSource.getRoutingDataSource();
System.err.println(Thread.currentThread().getName() + " determineCurrentLookupKey : " + lookupKey);
return lookupKey;
}
private static final ThreadLocal
5.自定义 动态切换数据库的注解
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@documented
public @interface TargetDataSource {
String value();
}
6.`切面拦截动态数据源注解
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(0)
@Aspect
@Component
public class RoutingAopAspect {
@Around("@annotation(targetDataSource)")
public Object routingWithDataSource(ProceedingJoinPoint joinPoint, TargetDataSource targetDataSource) throws Throwable {
try {
DynamicRoutingDataSource.setRoutingDataSource(targetDataSource.value());
return joinPoint.proceed();
} finally {
DynamicRoutingDataSource.removeRoutingDataSource();
}
}
}
以上配置基本完成,下面是 示例
7.Repository (dao层)
import com.example.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { }
8.service 自定义注解
@Slf4j
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
//写库
public List getList() {
List list = userRepository.findAll();
return list ;
}
//读库
@TargetDataSource(value = DataSourceEnum.slave)
public List getList() {
List list = userRepository.findAll();
return list ;
}



