SpringBoot多种数据源

数据库:Oracle +SqlServer
持久层框架:Mybatis Plus + Jpa

1,pom文件

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- Spring-Data-Redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--web模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Spring-Data-JPA-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- MybatisPlus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--Oracle驱动包-->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0</version>
        </dependency>
        <!-- SqlServer驱动包 -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>4.0</version>
        </dependency>
    </dependencies>

2,application配置文件

spring:
 #JPA
 jpa:
  show-sql: true
  open-in-view: true
  hibernate:
   ddl-auto: none
  #数据源
 datasource:
   #Oracle数据库(主数据库)
   master:
    jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
    username: 用户名
    password: 密码
    driver-class-name: oracle.jdbc.OracleDriver
   #从数据库(sql Server数据库)
   slave:
    jdbc-url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=NewBug
    username: 用户名
    password: 密码
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
   hikari:
    #数据库连接超时时间
    connection-timeout: 60000
    #控制池中连接的最长生命周期
    max-lifetime: 60000
    #最大连接数
    maximum-pool-size: 60
    #连接允许在连接池闲置的时间
    idle-timeout: 20000
    #验证与数据库连接的有效时间(每隔这么多时间就要去验证一次与数据库的时间是否有效)
    validation-timeout: 3000
    #心跳检测
    connection-test-query: SELECT 1 

# Mybatis-plus
mybatis-plus:
  # 放在resource目录 classpath:/mapper/*Mapper.xml
  mapper-locations: classpath:mapper/*Mapper.xml
  global-config:
    # 主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
    id-type: 2
    # 字段策略 0:"忽略判断",1:"非 NULL 判断",2:"非空判断"
    field-strategy: 2
    # 驼峰下划线转换
    db-column-underline: false
    # 刷新mapper 调试神器
    refresh-mapper: true
    # SQL 解析缓存,开启后多租户 @SqlParser 注解生效
    sql-parser-cache: true
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
    # 配置JdbcTypeForNull, oracle数据库必须配置
    jdbc-type-for-null: 'null'
    #用于打印mybatis的sql语句日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    

3,代码

  • Mybatis Plus 多种数据配置

1,MyDataSource注解

/**
 * 数据源注解
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface MyDataSource {
    String value() default "";
}

2,DatasourceConstants类

/**
 * 数据源常量
 */
public class DatasourceConstants {
    public static final String DATASOURCE1 = "master";
    public static final String DATASOURCE2 = "slave";
}

3,DataSourceContextHolder类

/**
 * 数据源容器
 */
public class DataSourceContextHolder {

    public static final ThreadLocal<String> HOLDER = new ThreadLocal<>();

    /**
     * 获取数据源名
     * @return
     */
    public static String getDataSource(){
        return HOLDER.get();
    }

    /**
     * 设置数据源名
     * @param dataSourceName
     */
    public static void setDataSource(String dataSourceName){
        HOLDER.set(dataSourceName);
    }

    /**
     * 移除数据源名
     */
    public  static void removeDataSource(){
        HOLDER.remove();
    }
}

4,DynamicDataSourceAspect类

/**
 * 数据源切面  需要在事务@Transactional之前运行
 */
@Component
@Aspect
@Order(-1)
public class DynamicDataSourceAspect {

    //切点表达式
    @Pointcut("@annotation(com.*.*.common.annotation.MyDataSource)")
    public void  pointcut(){

    }

    @Before("pointcut()")
    public void  beforeMethod(JoinPoint joinPoint) throws NoSuchMethodException {
        //获取class对象
        Class<?> clazz = joinPoint.getTarget().getClass();
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        //获取方法参数类型
        Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        //获取到Method类
        Method method = clazz.getMethod(methodName, parameterTypes);
        //获取到注解
        MyDataSource annotation = method.getAnnotation(MyDataSource.class);
        //获取注解上的值
        String dataSourceName = annotation.value();
        //设置数据源
        DataSourceContextHolder.setDataSource(dataSourceName);
    }

    @After("pointcut()")
    public void afterSwitchDS(JoinPoint joinPoint) {
        DataSourceContextHolder.removeDataSource();
    }
}

5,MasterDataSourcePropertise(主数据源)

/**
 * Oracle数据库配置文件
 */
@ConfigurationProperties(prefix="spring.datasource.master")
@Component
@Data
public class MasterDataSourcePropertise {

    private String jdbcUrl;

    private String username;

    private String password;

    private String driverClassName;
}

6,SlaveDataSourcePropertise(从数据源)

/**
 * sqlServer数据库配置文件
 */

@Component
@Data
@ConfigurationProperties(prefix="spring.datasource.slave")
public class SlaveDataSourcePropertise {

    private String jdbcUrl;

    private String username;

    private String password;

    private String driverClassName;
}

7,DynamicDataSource(动态数据源获取)

/**
 * 获取动态数据源
 */

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}

8,MybatisPlusConfig

/**
 * 定义MybatisPlusConfig配置类,该类是注册PaginationInterceptor
 */
@Configuration
//扫描mapper接口
@MapperScan("com.*.*.modules.dao.mapper")
public class MybatisPlusConfig {

    @Autowired
    private MasterDataSourcePropertise masterDataSourcePropertise;

    @Autowired
    private SlaveDataSourcePropertise slaveDataSourcePropertise;

    /**
     * 分页插件,自动识别数据库类型,注册PaginationInterceptor
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    @Bean
    public DataSource master() {
        DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName(masterDataSourcePropertise.getDriverClassName());
        dataSourceBuilder.username(masterDataSourcePropertise.getUsername());
        dataSourceBuilder.password(masterDataSourcePropertise.getPassword());
        dataSourceBuilder.url(masterDataSourcePropertise.getJdbcUrl());
        return dataSourceBuilder.build();
    }

    @Bean
    public DataSource slave() {
        DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName(slaveDataSourcePropertise.getDriverClassName());
        dataSourceBuilder.username(slaveDataSourcePropertise.getUsername());
        dataSourceBuilder.password(slaveDataSourcePropertise.getPassword());
        dataSourceBuilder.url(slaveDataSourcePropertise.getJdbcUrl());
        return dataSourceBuilder.build();
    }

    /**
     * 动态数据源配置
     * @return
     */
    @Bean
    @Primary
    public DataSource setDynamicDataSource( DataSource master,  DataSource slave) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        //设置默认的数据源,不设置会报错
        dynamicDataSource.setDefaultTargetDataSource(master);
        //配置多数据源,加入其他数据源到map中value
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatasourceConstants.DATASOURCE1, master);
        targetDataSources.put(DatasourceConstants.DATASOURCE2, slave);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(setDynamicDataSource(master() , slave()));
        //数据库相关设置
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        //添加分页功能(由于配置了多数据源,默认的分页不起作用,需重新添加),在此可以添加数据权限过滤器
        sqlSessionFactory.setPlugins(new Interceptor[]{paginationInterceptor()});
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        sqlSessionFactory.setConfiguration(configuration);
        return sqlSessionFactory.getObject();
    }
}

至此Mybatis Plus多种数据源配置完成了,下面我们再说一下JPA的多种数据源配置

  • JPA多种数据配置

1,DataSourceConfig

/**
 * jpa的数据源
 */
@Configuration
public class DataSourceConfig {

    @Autowired
    private MasterDataSourcePropertise masterDataSourcePropertise;

    @Autowired
    private SlaveDataSourcePropertise slaveDataSourcePropertise;

    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    public DataSource primaryDataSource() {
        DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName(masterDataSourcePropertise.getDriverClassName());
        dataSourceBuilder.username(masterDataSourcePropertise.getUsername());
        dataSourceBuilder.password(masterDataSourcePropertise.getPassword());
        dataSourceBuilder.url(masterDataSourcePropertise.getJdbcUrl());
        return dataSourceBuilder.build();
    }

    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    public DataSource secondaryDataSource() {
        DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName(slaveDataSourcePropertise.getDriverClassName());
        dataSourceBuilder.username(slaveDataSourcePropertise.getUsername());
        dataSourceBuilder.password(slaveDataSourcePropertise.getPassword());
        dataSourceBuilder.url(slaveDataSourcePropertise.getJdbcUrl());
        return dataSourceBuilder.build();
    }
}

2,PrimaryConfig

/**
 * jpa主数据源的配置
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactoryPrimary",
        transactionManagerRef="transactionManagerPrimary",
        basePackages= { "com.*.*.modules.dao.jpa" })//设置Repository所在位置
public class PrimaryConfig {

    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    private HibernateProperties hibernateProperties;

    private Map<String, Object> getVendorProperties() {
        Map<String,String> properties = new HashMap<>();
        properties.put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
        jpaProperties.setDatabase(Database.ORACLE);
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }

    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setShowSql(true);
        LocalContainerEntityManagerFactoryBean factoryBean  = builder
                .dataSource(primaryDataSource)
                .packages("com.*.*.modules.entity.bean") //设置实体类所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        return factoryBean;
    }

    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

3,SecondaryConfig

/**
 * jpa次数据源的配置
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactorySecondary",
        transactionManagerRef="transactionManagerSecondary",
        basePackages= {"com.*.*.modules.dao.jpa.slave"}) //设置Repository所在位置
public class SecondaryConfig {

    @Autowired
    @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    private HibernateProperties hibernateProperties;

    private Map<String, Object> getVendorProperties() {
        Map<String,String> properties = new HashMap<>();
        properties.put("hibernate.dialect","org.hibernate.dialect.SQLServer2008Dialect");
        jpaProperties.setDatabase(Database.SQL_SERVER);
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }

    @Bean(name = "entityManagerSecondary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(false);
        jpaVendorAdapter.setShowSql(true);
        LocalContainerEntityManagerFactoryBean factoryBean  = builder
                .dataSource(secondaryDataSource)
                .packages("com.*.*.modules.entity.pojo") //设置实体类所在位置
                .persistenceUnit("secondaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        return factoryBean;
    }

    @Bean(name = "transactionManagerSecondary")
    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }

}

JPA的配置比Mybatis Plus就少了很多,值得注意的是,如果需要实体类映射自动生成表,将代码中jpaVendorAdapter.setGenerateDdl(true),如果不想自动生成表,将其设置为false。
至此,SpringBoot多种数据源,并且使用Mybatis Plus和Spring Data JPA的配置全部完成了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

U文韬武略U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值