springboot配置多数据源的两种方式

       随着业务场景的复杂,单数据源已满足不了实际使用,多数源的配置成为了主流,笔者根据自己的项目经验总结了两种常用的多数据源配置方式,这里使用mybatis框架作为持久层,如何实现分享给大家||

    第①种:定义多个数据源连接,mybatis配置好不同的数据源映射不同的dao及domain,通常同一个数据源会放到一个package下,即此包下的dao接口全是查同一个数据源的数据;

    第②种:动态数据源切换,这种方式较为灵活,在程序运行时,把数据源动态织入到程序中,从而选择哪个源,主要用到的技术:annotation/spring aop/反射。

   代码实现:以双数据源举例

   ①:

包目录:

1)主数据源配置类

@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = {"com.bocom.datagenerate.dao.primaryDao"},sqlSessionFactoryRef ="primarySqlSessionFactory")
public class PrimaryConfig {
    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix="spring.datasource")
    public DataSource masterDataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "primarySqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mybatis/primaryMybatis/*.xml"));
        return sessionFactoryBean.getObject();
    }

    @Bean(name = "primaryTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("distrSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        return template;
    }
}

2)从数据源配置类

@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.bocom.datagenerate.dao.taskPushDao",sqlSessionFactoryRef = "taskPushSqlSessionFactory")
public class TaskPushConfig {


    @Bean(name = "taskPushDataSource")
    @ConfigurationProperties(prefix="primary.datasource")
    public DataSource masterDataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "taskPushSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("taskPushDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mybatis/taskPushMybatis/*.xml"));
        return sessionFactoryBean.getObject();
    }

    @Bean(name = "taskPushTransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("taskPushDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("smpSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("taskPushSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception{
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        return template;
    }
}

ps:启动类上加上如下注解,以免报错

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

 

②:

参考了这篇文章https://www.cnblogs.com/surge/p/3582248.html,在此感谢博主分享!

首先,定义一个注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource {
    String value();
}

然后,定义一个aop类

@Aspect
@Component
public class DataSourceAspect {

    @Before(value = "pointCut()")
    public void before(JoinPoint point) {
        Object target = point.getTarget();
        String method = point.getSignature().getName();
        Class<?>[] classz = target.getClass().getInterfaces();
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
        try {
            Method m = classz[0].getMethod(method, parameterTypes);
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource data = m.getAnnotation(DataSource.class);
                DynamicDataSourceHoler.putDataSource(data.value());
                System.out.println(data.value());
             }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Pointcut("execution(* com.alibaba.ghs.task.mapper.*.*(..))")
    public void pointCut() {

    }
}

其次,写一个类DynamicDataSource  继承AbstractRoutingDataSource,实现其determineCurrentLookupKey() 方法,该方法返回Map的key,master或slave。

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

class DynamicDataSourceHoler {
    public static final ThreadLocal<String> holder = new ThreadLocal<String>();

    public static void putDataSource(String name) {
        holder.set(name);
    }

    public static String getDataSource() {
        return holder.get();
    }
}

最后,数据源配置类:

@Configuration
public class DataSourceConfig {

    @Bean(name = "masterdatasource")
    public DriverManagerDataSource driverManagerDataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/ghs?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT&allowMultiQueries=true");
        ds.setUsername("root");
        ds.setPassword("xxxx");
        return ds;
    }

    @Bean(name = "slavedatasource")
    public DriverManagerDataSource driverManagerDataSource2() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://127.0.0.1:3306/quartz?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT&allowMultiQueries=true");
        ds.setUsername("root");
        ds.setPassword("xxxx");
        return ds;
    }

    @Bean(name = "dataSource")
    public DynamicDataSource dynamicDataSource(@Qualifier("masterdatasource") DriverManagerDataSource driverManagerDataSource,
                                               @Qualifier("slavedatasource") DriverManagerDataSource driverManagerDataSource2) {
        DynamicDataSource ds = new DynamicDataSource();
        Map map = new HashMap();
        map.put("master", driverManagerDataSource);
        map.put("slave", driverManagerDataSource2);
        ds.setTargetDataSources(map);
        ds.setDefaultTargetDataSource(driverManagerDataSource);
        ds.afterPropertiesSet();
        return ds;
    }

    @Bean(name = "transcationManager")
    public DataSourceTransactionManager manager(@Qualifier("dataSource") DynamicDataSource dynamicDataSource) {
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dynamicDataSource);
        return manager;
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean sb(@Qualifier("dataSource") DynamicDataSource dynamicDataSource, ApplicationContext applicationContext) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.alibaba.ghs.task.model");
        return sqlSessionFactoryBean;
    }

    @Bean
    public MapperScannerConfigurer MapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.alibaba.ghs.task.mapper");  //dao目录
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return mapperScannerConfigurer;
    }

使用:

public interface GhsMapper {

    @DataSource("master")
    public void add(Ghs ghs);

    @DataSource("slave")
    public void add2(Ghs ghs);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值