栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot+jpa+aop自定义注解多数据源配置

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot+jpa+aop自定义注解多数据源配置

springboot+jpa+aop自定义注解多数据源配置

背景 :数据同步项目,将接口返回的数据通过定时任务,将数据存储到数据库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 targetDataSources = new HashMap<>(2);
        targetDataSources.put(DataSourceEnum.master, masterDataSource);
        targetDataSources.put(DataSourceEnum.slave, slaveDataSource);
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
        //设置数据源
        dynamicRoutingDataSource.setTargetDataSources(targetDataSources);
        //设置默认选择的数据源
        dynamicRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
        dynamicRoutingDataSource.afterPropertiesSet();
        return dynamicRoutingDataSource;
    }


}

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 threadLocalDataSource = new ThreadLocal<>();


    public static void setRoutingDataSource(Object dataSource) {
        if (dataSource == null) {
            throw new NullPointerException();
        }
        threadLocalDataSource.set(dataSource);
        // System.err.println(Thread.currentThread().getName()+" set RoutingDataSource : " + dataSource);
    }

    public static Object getRoutingDataSource() {
        Object dataSourceType = threadLocalDataSource.get();
        if (dataSourceType == null) {
            threadLocalDataSource.set(DataSourceEnum.master);
            return getRoutingDataSource();
        }
        // System.err.println(Thread.currentThread().getName()+" get RoutingDataSource : " + dataSourceType);
        return dataSourceType;
    }

    public static void removeRoutingDataSource() {
        threadLocalDataSource.remove();
        // System.err.println(Thread.currentThread().getName()+" remove RoutingDataSource");
    }
}
 

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 ;
    }

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号