SpringBoot MybatisPlus Druid 多数据源项目

写在前面:本文主要介绍SpringBoot MybatisPlus和Druid这些组件下,如何创建多数据源(DataSource)的web项目。写这篇博客的原因就是我在搜索同类型的问题的时候,其他人写的博客非常不清晰,完全无法按照介绍的步骤来实现。我希望我写的这篇博客可以真的替看这篇博客的人能解决这类问题。如果你看完之后还是没有解决可以评论留言,甚至加我的微信(JB328258)帮你解决。因为我觉得我们中国人写技术博客有的时候太敷衍了,不要把博客当成一个记事本。而是要真正对不管是行业还是同样的从业人员有价值才有意义。

背景: 我们的web项目需要读取两个数据库里面的表的数据,然后就有了这个需求。但是我在网上搜索解决方法,很多人的博客都是写的连接两个数据源,并且还通过AOP动态切换数据源,但是我认为这种使用场景应该是非常非常少的。一般情况下的应用场景都是表的数据在多个库里面。然后web项目需要读多个库的数据进行汇合。

正文:

第一步:引入对于的SpringBoot MybatisPlus Druid的Jar包。这一步不赘述,网上示例很多。

第二步:  填写多个数据源的相关配置,如JDBC的连接地址,JDBC的数据库等。

           1. cmdb代表一个数据库。

           2. compass代表一个数据库。

spring:
  datasource:
    cmdb:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://192.168.60.11:3306/cmdb_docker?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
      username: YourXXX
      password: YourXXX
      initial-size: 0
      min-idle: 1
      max-active: 20
      max-wait: 60000
      remove-abandoned: true
      remove-abandoned-timeout: 180
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      filters: stat,wall,log4j2
    compass:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://192.168.60.11:3306/compass?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
      username: YourXXX
      password: YourXXX
      initial-size: 0
      min-idle: 1
      max-active: 20
      max-wait: 60000
      remove-abandoned: true
      remove-abandoned-timeout: 180
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      filters: stat,wall,log4j2

第三步:创建对应的MybatisPlus的分页插件如下

@Configuration
public class MybatisPlusConfig {

    /**
     * 分页插件
     * @return
     */

    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor page = new PaginationInterceptor();
        page.setDialectType("mysql");
        return page;
    }

}

第四步:分别创建两个DataSource对应的Config,注意看下面代码里面的备注,比较重要。

4.1 创建第一个DataSource的Config

//创建Compass数据的DataSource数据源
@Configuration
// basePackages 是扫描的Compass库对应的Mapper
@MapperScan(basePackages = "com.ximalaya.compass.core.mapper",sqlSessionFactoryRef = "compassFactory")
public class CompassDataSourceConfig {


    @Autowired
    PaginationInterceptor paginationInterceptor;


    @Bean(name="compass")
    @ConfigurationProperties("spring.datasource.compass")
    public DataSource createCmdbDataSource(){
        return new DruidDataSource();
    }

    @Bean(name = "compassFactory")
    public SqlSessionFactory createCompassFactory(@Qualifier("compass") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);

        //这里是配置Mybatis的Configuration
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);

        
        factoryBean.setConfiguration(configuration);
        //这里是添加Mybatis的分页插件
        factoryBean.setPlugins(new Interceptor[]{paginationInterceptor});

        //这里是填写Compass这个库对应的Mapper.xml文件
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis-compass/*.xml"));
        return factoryBean.getObject();
    }

    @Bean(name = "compassSqlSessionTemplate")
    public SqlSessionTemplate createCompassSqlSessionTemplate(@Qualifier("compassFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

4.2 创建第二个DataSource的Config

@Configuration
@MapperScan(basePackages = "com.ximalaya.compass.collector.mapper",sqlSessionFactoryRef = "cmdbFactory")
public class CmdbDockerDataSourceConfig {

    @Autowired
    PaginationInterceptor paginationInterceptor;

    @Bean(name="cmdb_docker")
    @ConfigurationProperties("spring.datasource.cmdb")
    public DataSource createCmdbDataSource(){
        return new DruidDataSource();
    }

    @Bean(name = "cmdbFactory")
    public SqlSessionFactory createCmdbFactory(@Qualifier("cmdb_docker") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        factoryBean.setConfiguration(configuration);
        factoryBean.setPlugins(new Interceptor[]{paginationInterceptor});
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis-cmdb/*.xml"));
        return factoryBean.getObject();
    }

    @Bean(name = "cmdbSqlSessionTemplate")
    public SqlSessionTemplate createCmdbSqlSessionTemplate(@Qualifier("cmdbFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

结尾:至此所有的创建和修改都完成,启动SpringBoot项目使用对应的Service就可以访问对应的数据库了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现多主多从,读写分离的功能,可以通过使用MybatisPlus和Druid来实现。下面是大致的步骤: 1. 首先需要配置多个数据源,分别对应主库和从库。可以在application.properties或application.yml中配置多个数据源。 2. 在SpringBoot的启动类中,使用@Primary注解指定默认的数据源。 3. 使用Druid来配置数据源,可以通过使用@DataSource注解来指定具体的数据源。 4. 配置MybatisPlus的分页插件和动态数据源插件。分页插件可以使用PaginationInterceptor类,动态数据源插件可以使用DynamicDataSourcePlugin类。 5. 在Mapper接口中,使用@Mapper注解来指定具体的Mapper类,同时使用@DataSource注解来指定具体的数据源。 6. 在Service层中,可以通过使用@Transactional注解来实现事务管理。 下面是一个简单的配置示例: ```java @Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public DataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("slaveDataSource") DataSource slaveDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DynamicDataSourceEnum.MASTER.getValue(), masterDataSource); targetDataSources.put(DynamicDataSourceEnum.SLAVE.getValue(), slaveDataSource); DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(masterDataSource); return dynamicDataSource; } @Bean public SqlSessionFactory sqlSessionFactory(DataSource dynamicDataSource) throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dynamicDataSource); sqlSessionFactoryBean.setPlugins(new Interceptor[]{ new PaginationInterceptor(), new DynamicDataSourcePlugin() }); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } } ``` ```java public enum DynamicDataSourceEnum { MASTER("master"), SLAVE("slave"); private String value; DynamicDataSourceEnum(String value) { this.value = value; } public String getValue() { return value; } } ``` ```java @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented public @interface DataSource { DynamicDataSourceEnum value() default DynamicDataSourceEnum.MASTER; } ``` ```java public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSource(); } } ``` ```java public class DynamicDataSourceContextHolder { private static final ThreadLocal<DynamicDataSourceEnum> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSource(DynamicDataSourceEnum dataSource) { CONTEXT_HOLDER.set(dataSource); } public static DynamicDataSourceEnum getDataSource() { return CONTEXT_HOLDER.get(); } public static void clearDataSource() { CONTEXT_HOLDER.remove(); } } ``` ```java @Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @DataSource(DynamicDataSourceEnum.MASTER) @Override public void addUser(User user) { userMapper.insert(user); } @DataSource(DynamicDataSourceEnum.SLAVE) @Override public User getUser(Long id) { return userMapper.selectById(id); } } ``` 这样就可以实现多主多从,读写分离的功能了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值