Spring+MybatisPlus实现多数据源

DatasourceConfig 

package com.tonytaotao.dtsc.common.configuration.datasouce.normal; 

import com.alibaba.druid.pool.DruidDataSource; 
import com.tonytaotao.dtsc.common.configuration.datasouce.DBTypeEnum; 
import com.tonytaotao.dtsc.common.configuration.datasouce.DynamicDataSource; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Primary; 
import javax.sql.DataSource; 
import java.util.HashMap; 
import java.util.Map; 

@Configuration 
public class DatasourceConfig { 

    /*------------------------------------------------- 普通多数据源----------------------------------------------*/ 
    @Bean("multipleDataSource") 
    @Primary 
    public DataSource multipleDataSource() { 
        DynamicDataSource dynamicDataSource = new DynamicDataSource(); 
        Map< Object, Object > targetDataSources = new HashMap<>(); 
        targetDataSources.put(DBTypeEnum.ONE.getCode(), createDataSourceOne()); 
        targetDataSources.put(DBTypeEnum.TWO.getCode(), createDataSourceTwo()); 
        dynamicDataSource.setTargetDataSources(targetDataSources); 
        dynamicDataSource.setDefaultTargetDataSource(createDataSourceOne()); 
        return dynamicDataSource; 
    } 


    private DataSource createDataSourceOne() { 
        DruidDataSource druidDataSource = createDataSourceBase(); 
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/dtsc?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=UTF8&serverTimezone=GMT"); 
        druidDataSource.setUsername("root"); 
        druidDataSource.setPassword("123456"); 
        return druidDataSource; 
    } 


    private DataSource createDataSourceTwo() { 
        DruidDataSource druidDataSource = createDataSourceBase(); 
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/dtsc_1?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=UTF8&serverTimezone=GMT"); 
        druidDataSource.setUsername("root"); 
        druidDataSource.setPassword("123456"); 
        return druidDataSource; 
    } 


    private DruidDataSource createDataSourceBase() { 
        DruidDataSource druidDataSource = new DruidDataSource(); 
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); 
        druidDataSource.setInitialSize(50); 
        druidDataSource.setMaxActive(100); 
        druidDataSource.setMinIdle(5); 
        druidDataSource.setMaxWait(1000); 
        druidDataSource.setPoolPreparedStatements(false); 
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(-1); 
        druidDataSource.setValidationQuery("SELECT 1"); 
        druidDataSource.setValidationQueryTimeout(1); 
        druidDataSource.setTestOnBorrow(false); 
        druidDataSource.setTestOnReturn(false); 
        druidDataSource.setTestWhileIdle(true); 
        druidDataSource.setTimeBetweenEvictionRunsMillis(60000); 
        druidDataSource.setMinEvictableIdleTimeMillis(30000); 
        return druidDataSource; 
    } 

}

 MybatisPlusConfig

package com.tonytaotao.dtsc.common.configuration.datasouce.normal; 

import com.baomidou.mybatisplus.annotation.DbType; 
import com.baomidou.mybatisplus.annotation.FieldStrategy; 
import com.baomidou.mybatisplus.annotation.IdType; 
import com.baomidou.mybatisplus.core.MybatisConfiguration; 
import com.baomidou.mybatisplus.core.config.GlobalConfig; 
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector; 
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor; 
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Profile; 
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 
import javax.sql.DataSource; 
import java.io.IOException; 

@Configuration 
@MapperScan({"com.tonytaotao.dtsc.*.mapper"}) 
public class MybatisPlusConfig { 

    /** 
    * 性能分析插件 
    * @return 
    */ 
    @Bean 
    @Profile({"dev","sit"}) 
    public PerformanceInterceptor performanceInterceptor() { 
        return new PerformanceInterceptor(); 
    } 

    /** 
    * 分页插件 
    * @return 
    */ 
    @Bean 
    public PaginationInterceptor paginationInterceptor() { 
        return new PaginationInterceptor(); 
    } 

    /** 
    * 
    * @return 
    */ 
    @Bean("sqlSessionFactory") 
    public MybatisSqlSessionFactoryBean sqlSessionFactory(@Qualifier("multipleDataSource") DataSource multipleDataSource) { 
        try { 
            MybatisSqlSessionFactoryBean sqlSessionFactoryBean = mybatisSqlSessionFactoryBean(); 
            sqlSessionFactoryBean.setDataSource(multipleDataSource); 
            return sqlSessionFactoryBean; 
        } catch (IOException e) { 
            e.printStackTrace(); 
            return null; 
        } 
    } 

    private MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean() throws IOException{ 
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); 
        mybatisSqlSessionFactoryBean.setGlobalConfig(globalConfig()); 
        mybatisSqlSessionFactoryBean.setConfiguration(mybatisConfiguration()); 
        mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/tonytaotao/dtsc/*/mapper/xml/*Mapper.xml")); 
        mybatisSqlSessionFactoryBean.setTypeAliasesPackage("com.tonytaotao.dtsc.*.entity"); 
        return mybatisSqlSessionFactoryBean; 
    } 

    private GlobalConfig globalConfig() { 
        GlobalConfig globalConfig = new GlobalConfig(); 
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig(); 
        dbConfig.setIdType(IdType.AUTO); 
        dbConfig.setDbType(DbType.MYSQL); 
        dbConfig.setFieldStrategy(FieldStrategy.NOT_EMPTY); 
        dbConfig.setTableUnderline(true); 
        dbConfig.setLogicDeleteValue("0"); 
        dbConfig.setLogicNotDeleteValue("1"); 
        globalConfig.setDbConfig(dbConfig); 

        LogicSqlInjector logicSqlInjector = new LogicSqlInjector(); 
        globalConfig.setSqlInjector(logicSqlInjector); 
    
        return globalConfig; 
    } 

    private MybatisConfiguration mybatisConfiguration() { 
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration(); 
        // 源码里面如果有configuration, 不会注入BaseMapper 里面的方法, 所以这里要这样写 
        mybatisConfiguration.init(globalConfig()); 
        mybatisConfiguration.setMapUnderscoreToCamelCase(true); 
        mybatisConfiguration.setCacheEnabled(false); 
    
        return mybatisConfiguration; 
    } 

}

 TransationConfig

package com.tonytaotao.dtsc.common.configuration.datasouce.normal; 

import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.jdbc.datasource.DataSourceTransactionManager; 

import javax.sql.DataSource; 

/** 
* @author wujintao 
* 
* Configuration 类似于spring 配置文件,负责注册bean 
* ComponentScan 注解类查找规则定义 <context:component-scan/> 
* EnableAspectJAutoProxy 激活Aspect 自动代理 <aop:aspectj-autoproxy/> 
* proxy-target-class : 默认为false 表示使用JDK 动态代理。如果实现了至少一个接口,Spring 会优先选择使用JDK 动态代理,若果没有实现任何接口,则spring 会选择CGLIB 动态代理,强制使用CGLIB 动态代理,使用以下配置 
* exposeProxy : springAOP 只会拦截public 方法,不会拦截provided 和private 方法,并且不会拦截public 方法内部调用的其他方法,也就是说只会拦截代理对象的方法,即增强的是代理对象,而不是原对象, 设置就可以暴露出代理对象,拦截器会获取代理对象,并且将代理对象转换成原对象。从而对内部调用的方法进行增强 
* EnableTransactionManagement 启用注解式事务管理 <tx:annotation-driven /> 
*/ 
@Configuration 
@EnableTransactionManagement 
@EnableAspectJAutoProxy(exposeProxy = true) 
public class TransationConfig { 

    //@Bean 
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("multipleDataSource") DataSource multipleDataSource) { 
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); 
        transactionManager.setDataSource(multipleDataSource); 
        return transactionManager; 
    } 
}

  DBTypeEnum 

package com.tonytaotao.dtsc.common.configuration.datasouce; 

import lombok.Getter; 

public enum DBTypeEnum { 
    ONE("ONE", "db one"), 
    TWO("TWO", "db two"); 

    DBTypeEnum(String code, String msg) { 
        this.code = code; 
        this.msg = msg; 
    } 

    @Getter 
    private String code; 
    private String msg; 
}

 DBAnnotation 

package com.tonytaotao.dtsc.common.configuration.datasouce; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface DBAnnotation { 
    DBTypeEnum dbSource() default DBTypeEnum.ONE; 
}

DBAspect 

package com.tonytaotao.dtsc.common.configuration.datasouce; 

import lombok.extern.slf4j.Slf4j; 
import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 
import org.aspectj.lang.annotation.Pointcut; 
import org.aspectj.lang.reflect.MethodSignature; 
import org.springframework.core.annotation.Order; 
import org.springframework.stereotype.Component; 

import java.lang.reflect.Method; 

@Component 
@Aspect 
@Order(-100) 
@Slf4j 
public class DBAspect { 

    @Pointcut("execution(* com.tonytaotao.dtsc.*.service..*.*(..))") 
    private void pointcut() { 
    } 

    @Before("pointcut()") 
    public void before(JoinPoint joinPoint) { 
        Object target = joinPoint.getTarget(); 
        String methodName = joinPoint.getSignature().getName(); 
        Class<?> clazz = target.getClass(); 

        log.info("before [ class = {}, method = {} ] execute", clazz.getName(), methodName); 

        Class<?>[] parameterTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes(); 

        try { 

            Method method = clazz.getMethod(methodName, parameterTypes); 

            if (method != null) { 
                if (method.getDeclaringClass().isAnnotationPresent(DBAnnotation.class) && !method.isAnnotationPresent(DBAnnotation.class)) { 
                    DBAnnotation dbAnnotation = method.getDeclaringClass().getAnnotation(DBAnnotation.class); 
                    DBContextHolder.setDbType(dbAnnotation.dbSource()); 
                    log.info("[class = {}, method = {} ] 切换类级数据源 [ {} ] 成功", clazz.getName(), methodName, dbAnnotation.dbSource()); 
                } else if ( method.isAnnotationPresent(DBAnnotation.class)) { 
                    DBAnnotation dbAnnotation = method.getAnnotation(DBAnnotation.class); 
                    DBContextHolder.setDbType(dbAnnotation.dbSource()); 
                    log.info("[class = {}, method = {} ] 切换方法级数据源 [ {} ] 成功", clazz.getName(), methodName, dbAnnotation.dbSource()); 
                } else { 
                    DBContextHolder.setDbType(DBTypeEnum.ONE); 
                    log.info("[class = {}, method = {} ] 切换默认数据源 [ {} ] 成功", clazz.getName(), methodName, DBTypeEnum.ONE); 
                } 
            } 

            } catch (Exception e) { 
            log.error(" 数据源切换异常", e); 
        } 
    } 

}

 DBContextHolder 

package com.tonytaotao.dtsc.common.configuration.datasouce; 

public class DBContextHolder { 

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

    /** 
    * 设置数据源 
    * @param dbTypeEnum 
    */ 
    public static void setDbType(DBTypeEnum dbTypeEnum) { 
        contextHolder.set(dbTypeEnum.getCode()); 
    } 

    /** 
    * 取得当前数据源 
    * @return 
    */ 
    public static String getDbType() { 
        return (String) contextHolder.get(); 
    } 

    /** 
    * 清除上下文数据 
    */ 
    public static void clearDbType() { 
        contextHolder.remove(); 
    } 
}

DynamicDataSource 

package com.tonytaotao.dtsc.common.configuration.datasouce; 

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 

public class DynamicDataSource extends AbstractRoutingDataSource { 

    @Override 
    protected Object determineCurrentLookupKey() { 
        return DBContextHolder.getDbType(); 
    } 
}

 

使用方式

只要在 service 实现类的方法上或者类上加上 @DBAnnotation 指定数据源,就能实现自动切换数据源

 

转载于:https://my.oschina.net/TonyTaotao/blog/2980518

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Spring Boot和MyBatis Plus多数据源配置MySQL和PostgreSQL,你可以按照以下步骤进行操作: 1. 首先,在你的Spring Boot项目中添加MySQL和PostgreSQL的依赖。在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> ``` 2. 接下来,配置数据源。在`application.properties`或`application.yml`文件中添加以下配置: ```yaml # MySQL 数据源配置 spring.datasource.mysql.url=jdbc:mysql://localhost:3306/mysql_db spring.datasource.mysql.username=root spring.datasource.mysql.password=123456 # PostgreSQL 数据源配置 spring.datasource.postgresql.url=jdbc:postgresql://localhost:5432/postgresql_db spring.datasource.postgresql.username=postgres spring.datasource.postgresql.password=123456 ``` 3. 然后,创建数据源配置类。创建两个数据源的配置类,分别用于MySQL和PostgreSQL。例如,创建名为`MySQLDataSourceConfig`和`PostgreSQLDataSourceConfig`的类,并分别添加`@Configuration`和`@ConfigurationProperties`注解。 ```java @Configuration @ConfigurationProperties(prefix = "spring.datasource.mysql") public class MySQLDataSourceConfig { private String url; private String username; private String password; // 省略 getter 和 setter 方法 } ``` ```java @Configuration @ConfigurationProperties(prefix = "spring.datasource.postgresql") public class PostgreSQLDataSourceConfig { private String url; private String username; private String password; // 省略 getter 和 setter 方法 } ``` 4. 接下来,配置数据源。在`DataSourceConfig`类中,创建两个数据源的`DataSource`实例,并将它们注入到`SqlSessionFactory`中。 ```java @Configuration public class DataSourceConfig { @Bean(name = "mysqlDataSource") @ConfigurationProperties(prefix = "spring.datasource.mysql") public DataSource mysqlDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "postgresqlDataSource") @ConfigurationProperties(prefix = "spring.datasource.postgresql") public DataSource postgresqlDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("mysqlDataSource") DataSource mysqlDataSource, @Qualifier("postgresqlDataSource") DataSource postgresqlDataSource) throws Exception { SqlSessionFactoryBean sessionFactory
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值