zoukankan      html  css  js  c++  java
  • SpirngBoot整合Mybatis Plus多数据源

    导读

      有一个这样子的需求,线上正在跑的业务,由于业务发展需要,需重新开发一套新系统,等新系统开发完成后,需要无缝对接切换,当初具体设计见草图。

    添加依赖

            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.16</version>
                <!--scope=provided,说明它是在编译阶段生效,不需要打入包中,Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件-->
                <scope>provided</scope>
            </dependency>
            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!--mybatis plus和spring boot整合-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.4.0</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>

    application.properties

    server.port=9999
    spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.master.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
    spring.datasource.master.username=root
    spring.datasource.master.password=root
    
    spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.slave.jdbc-url=jdbc:mysql://127.0.0.1/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false
    spring.datasource.slave.username=root
    spring.datasource.slave.password=root

    2种方式创建DataSource

    Master配置,使用druid连接池

    import com.alibaba.druid.pool.DruidDataSource;
    import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.env.Environment;
    
    import javax.sql.DataSource;
    
    /**
     * @Author:chenyanbin
     */
    @Configuration
    @MapperScan(basePackages = "com.example.demo.mapper", sqlSessionFactoryRef = "masterSqlSessionFactory")
    public class MasterDataSourceConfig {
        @Autowired
        private Environment env;
    
        @Primary
        @Bean(name = "masterDataSource")
    //    @ConfigurationProperties("spring.datasource.master")
        public DataSource masterDataSource() {
    //        return DataSourceBuilder.create().build();
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setUrl(env.getProperty("spring.datasource.master.url"));
            dataSource.setUsername(env.getProperty("spring.datasource.master.username"));
            dataSource.setPassword(env.getProperty("spring.datasource.master.password"));
            dataSource.setDriverClassName(env.getProperty("spring.datasource.master.driver-class-name"));
            //配置初始化大小、最小、最大
            dataSource.setMinIdle(10);
            //配置初始化大小、最小、最大
            dataSource.setMaxActive(200);
            //配置初始化大小、最小、最大
            dataSource.setInitialSize(10);
            //配置获取连接等待超时的时间
            dataSource.setMaxWait(60000);
            //配置一个连接在池中最小生存的时间,单位是毫秒
            dataSource.setMinEvictableIdleTimeMillis(300000);
            //配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            dataSource.setTimeBetweenEvictionRunsMillis(60000);
            //默认的testWhileIdle=true,testOnBorrow=false,testOnReturn=false
            dataSource.setValidationQuery("SELECT 1");
            //申请连接时执行validationQuery检测连接是否有效
            dataSource.setTestOnBorrow(false);
            //建议配置为true,不影响性能,并且保证安全性。
            dataSource.setTestWhileIdle(true);
            //是否缓存preparedStatement,也就是PSCache
            dataSource.setPoolPreparedStatements(false);
            return dataSource;
        }
    
        @Bean(name = "masterSqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
            MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
    
            return sessionFactoryBean.getObject();
        }
    }

    Slave配置

    import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    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 javax.sql.DataSource;
    
    /**
     * @Author:chenyanbin
     */
    @Configuration
    @MapperScan(basePackages = "com.example.demo.mapper2",sqlSessionFactoryRef = "slaveSqlSessionFactory")
    public class SlaveDataSourceConfig {
        @Bean(name = "slaveDataSource")
        @ConfigurationProperties("spring.datasource.slave")
        public DataSource slaveDataSource(){
            return DataSourceBuilder.create().build();
        }
    
        @Bean(name = "slaveSqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
            MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            return sessionFactoryBean.getObject();
        }
    }

    注意

      master和slave扫描不同的mapper包路径!!!!!!

      如果需要指定.xml文件,需这样配置!!!

        @Bean(name = "masterSqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
            MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                    .getResources("classpath:mapper/**/*.xml"));
            return sessionFactoryBean.getObject();
        }

    MybatisPlus分页插件设置

    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * MybatisPlus分页配置
     *
     * @Author:chenyanbin
     */
    @Configuration
    public class MybatisPlusPageConfig {
    
        /**
         * 新版分页插件
         *
         * @return
         */
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
            return mybatisPlusInterceptor;
        }
    }
        @Bean(name = "masterSqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(
                @Qualifier("masterDataSource") DataSource dataSource,
                @Qualifier("mybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor
        ) throws Exception {
            MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                    .getResources("classpath:mapper/**/*.xml"));
            sessionFactoryBean.setPlugins(mybatisPlusInterceptor);
            return sessionFactoryBean.getObject();
        }

    设置填充字段

    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    
    /**
     * @Author:chenyanbin
     */
    @Component
    public class CustomMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            //属性名称,不是字段名称
            this.setFieldValByName("createTime", CommonUtil.getCurrentDate(), metaObject);
            this.setFieldValByName("createUserId", CommonUtil.getCurrentUserId(), metaObject);
            this.setFieldValByName("createUserName", CommonUtil.getCurrentUserName(), metaObject);
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
            //属性名称,不是字段名称
            this.setFieldValByName("updateTime", CommonUtil.getCurrentDate(), metaObject);
            this.setFieldValByName("updateUserId", CommonUtil.getCurrentUserId(), metaObject);
            this.setFieldValByName("updateUserName", CommonUtil.getCurrentUserName(), metaObject);
        }
    }
    /**
     * <p>
     * 角色信息表
     * </p>
     *
     * @author chenyanbin
     * @since 2021-09-28
     */
    @Data
    @TableName("sys_role")
    @ApiModel(value = "SysRoleDO对象", description = "角色信息表")
    public class RoleDO implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @ApiModelProperty(value = "角色ID")
        @TableId(value = "id", type = IdType.AUTO)
        private Long id;
    
        @ApiModelProperty(value = "角色名称")
        private String roleName;
    
        @ApiModelProperty(value = "角色状态(0正常 1停用)")
        private byte status;
    
        @ApiModelProperty(value = "备注")
        private String remark;
    
        @ApiModelProperty(value = "创建时间")
        @TableField(value = "create_time", fill = FieldFill.INSERT)
        private Date createTime;
    
        @ApiModelProperty(value = "创建人id")
        @TableField(value = "create_user_id", fill = FieldFill.INSERT)
        private Long createUserId;
    
        @ApiModelProperty(value = "创建人姓名")
        @TableField(value = "create_user_name", fill = FieldFill.INSERT)
        private String createUserName;
    
        @ApiModelProperty(value = "修改时间")
        @TableField(value = "update_time", fill = FieldFill.UPDATE)
        private Date updateTime;
    
        @ApiModelProperty(value = "修改人id")
        @TableField(value = "update_user_id", fill = FieldFill.UPDATE)
        private Long updateUserId;
    
        @ApiModelProperty(value = "修改人姓名")
        @TableField(value = "update_user_name", fill = FieldFill.UPDATE)
        private String updateUserName;
    
    
    }
        import com.baomidou.mybatisplus.core.config.GlobalConfig;
    
    
    
        @Bean(name = "masterSqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(
                @Qualifier("masterDataSource") DataSource dataSource,
                @Qualifier("mybatisPlusInterceptor") MybatisPlusInterceptor mybatisPlusInterceptor,
                @Qualifier("customMetaObjectHandler") CustomMetaObjectHandler customMetaObjectHandler
        ) throws Exception {
            MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                    .getResources("classpath:mapper/**/*.xml"));
            //mybatis plus分页插件
            sessionFactoryBean.setPlugins(mybatisPlusInterceptor);
            //自动填充字段
            GlobalConfig globalConfig=new GlobalConfig();
            globalConfig.setMetaObjectHandler(customMetaObjectHandler);
            sessionFactoryBean.setGlobalConfig(globalConfig);
            return sessionFactoryBean.getObject();
        }

    多数据源事务问题

    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    
    import javax.sql.DataSource;
    
    /**
     * 事务
     *
     * @Author:chenyanbin
     */
    @Configuration
    public class CustomTransactionHandler {
        @Bean(name = "masterTransaction")
        public DataSourceTransactionManager masterTransaction(
                @Qualifier("masterDataSource") DataSource dataSource
        ) {
            return new DataSourceTransactionManager(dataSource);
        }
    
        @Bean(name = "historyTransaction")
        public DataSourceTransactionManager historyTransaction(
                @Qualifier("historyDataSource") DataSource dataSource
        ) {
            return new DataSourceTransactionManager(dataSource);
        }
    }

    指定使用那个数据源的事务

    @Transactional(transactionManager = "masterTransaction")
    public void remove(Long id) {}

    启动类

    @SpringBootApplication(
            exclude = {DataSourceAutoConfiguration.class, MybatisPlusAutoConfiguration.class}
    )

    启动类上排查,自动装配,使用我们自定义的多数据源!!!

    演示

      多个数据源,同时也是支持事务的

    作者:陈彦斌

    个性签名:没有学不会的技术,只有不学习的人!
    联系方式:543210188(WeChat/QQ),推荐WeChat
  • 相关阅读:
    NYOJ 10 skiing DFS+DP
    51nod 1270 数组的最大代价
    HDU 4635 Strongly connected
    HDU 4612 Warm up
    POJ 3177 Redundant Paths
    HDU 1629 迷宫城堡
    uva 796
    uva 315
    POJ 3180 The Cow Prom
    POJ 1236 Network of Schools
  • 原文地址:https://www.cnblogs.com/chenyanbin/p/15504125.html
Copyright © 2011-2022 走看看