• Springboot 多数据源配置,结合tk-mybatis


    一、前言

        作为一个资深的CRUD工程师,我们在实际使用springboot开发项目的时候,难免会遇到同时使用多个数据库的情况,比如前脚刚查询mysql,后脚就要查询sqlserver。

    这时,我们很直观的就会想到,为springboot配置多个数据源,需要用哪个数据库连接,直接@Autowired不就行了。那么问题来了,怎么配置呢?

     ********************************************************************************************************************************************************************

                                                                                               退后,我要开始装逼了

     ********************************************************************************************************************************************************************

     

    二、前期工作

    1.数据库。

    这里我准备了一个mysql数据库和一个sqlserver数据库。

    Mysql脚本:

    DROP TABLE IF EXISTS `tb_user`;
    CREATE TABLE `tb_user`  (
      `id` int(8) NOT NULL,
      `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of tb_user
    -- ----------------------------
    INSERT INTO `tb_user` VALUES (0, '张三');
    INSERT INTO `tb_user` VALUES (1, '李四');
    INSERT INTO `tb_user` VALUES (2, '王五');
    INSERT INTO `tb_user` VALUES (3, '赵六');
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    sqlserver脚本:

    IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[test]') AND type IN ('U'))
    	DROP TABLE [dbo].[test]
    GO
    
    CREATE TABLE [dbo].[test] (
      [id] int  NOT NULL,
      [career] varchar(255) COLLATE Chinese_PRC_90_CI_AS  NULL
    )
    GO
    
    ALTER TABLE [dbo].[test] SET (LOCK_ESCALATION = TABLE)
    GO
    
    -- ----------------------------
    -- Records of test
    -- ----------------------------
    INSERT INTO [dbo].[test] ([id], [career]) VALUES (N'1', N'软件工程师')
    GO
    
    INSERT INTO [dbo].[test] ([id], [career]) VALUES (N'2', N'硬件工程师')
    GO
    
    INSERT INTO [dbo].[test] ([id], [career]) VALUES (N'3', N'理财顾问')
    GO
    
    INSERT INTO [dbo].[test] ([id], [career]) VALUES (N'4', N'律师')
    GO
    
    INSERT INTO [dbo].[test] ([id], [career]) VALUES (N'5', N'数学家')
    GO
    
    -- ----------------------------
    -- Primary Key structure for table test
    -- ----------------------------
    ALTER TABLE [dbo].[test] ADD CONSTRAINT [PK__test__3213E83F1910436D] PRIMARY KEY CLUSTERED ([id])
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)  
    ON [PRIMARY]
    GO
    

    2.项目依赖。

        springboot版本:2.0.6.RELEASE

        依赖这里就不贴出来了,都是常见的几个starter而已。

    tk.mybatis插件

        这里我着重说一下tk.mybatis插件的配置。因为我们要使用该插件自动生成mapper等相关文件,但是我们又使用了两个不同的数据库,因此,需要对该插件分别作不同的参数配置,然后分别自动生成。

    注意不要同时配置插件,不然会插件引入冲突。

        关于如何使用tk.mybatis插件,请移步 使用mybatis-generator插件结合tk.mybatis自动生成mapper二三事 

        <!-- mysql 数据库 -->
          <!--<plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version>
            <configuration>
              <configurationFile>src/main/resources/generator/generatorConfig-mysql.xml</configurationFile>
              <overwrite>true</overwrite>
              <verbose>true</verbose>
            </configuration>
            <dependencies>
              <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
              </dependency>
              <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper</artifactId>
                <version>3.4.4</version>
              </dependency>
            </dependencies>
          </plugin>-->
          <!-- sqlserver 数据库 -->
          <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version>
            <configuration>
              <configurationFile>src/main/resources/generator/generatorConfig-sqlserver.xml</configurationFile>
              <overwrite>true</overwrite>
              <verbose>true</verbose>
            </configuration>
            <dependencies>
              <dependency>
                <groupId>com.microsoft.sqlserver</groupId>
                <artifactId>sqljdbc4</artifactId>
                <version>${sqlserver.sqljdbc4.version}</version>
              </dependency>
              <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper</artifactId>
                <version>3.4.4</version>
              </dependency>
            </dependencies>
          </plugin>
    

    三、重头戏

       1.spring配置文件

        我们知道在application.yml(properties)文件中,可以配置一个数据源,spring在启动时,会自动加载该配置,并实例化数据库连接:

    spring:
    datasource:
    type: com.zaxxer.hikari.HikariDataSource
    url: jdbc:mysql://192.168.139.129:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    hikari:
    minimum-idle: 1
    maximum-pool-size: 20

        但是我们现在有多个数据源怎么办呢?难道直接粗暴的写两个?spring能自动识别两个数据源配置么?

        这时,我们就需要手动使用@Bean的方式在代码中进行不同数据源的实例化配置了。为了更方便的管理配置信息,所以,我们仍然将配置信息写在application.yml中便于属性自动注入,但同时,对每一组数据源配置信息,需要加上前缀用以区分。

    spring:
      datasource:
        test-mysql:
          type: com.zaxxer.hikari.HikariDataSource
          url: jdbc:mysql://192.168.139.129:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
          username: root
          password: root
          driver-class-name: com.mysql.jdbc.Driver
          hikari:
            minimum-idle: 1
            maximum-pool-size: 20
    
        test-sqlserver:
          type: com.zaxxer.hikari.HikariDataSource
          url: jdbc:sqlserver://192.168.139.129;DatabaseName=dbo
          username: sa
          password: qwe!@#123
          driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
          hikari:
            minimum-idle: 1
            maximum-pool-size: 20
    

    2.手动配置数据源  

          通过手动配置数据源,分别实例化不同的数据源连接对象,以实现spring的多数据源配置。由于多个数据源对于spring来说都是DataSource及其相关类型的Bean,那么在spring容器进行DataSource实例化注入容器的时候,就会很困惑:WDNMD,你给劳资搞了几个数据源啊?这么多“妹子”,我先“嘿咻”谁?所以,为了让spring能够顺利的实例化我们配置的所有DataSource,就需要我们手动指定优先级,使用@Primary注解告知spring当前Bean的优先级更高。

     主数据源(mysql)

    package com.zhangyu.springboot.multidatasource.config;
    
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import tk.mybatis.spring.annotation.MapperScan;
    
    import javax.sql.DataSource;
    
    // mysql数据源配置(主数据源)
    @Configuration
    @MapperScan(basePackages = "com.zhangyu.springboot.multidatasource.mapper.mysql", sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
    public class TestMysqlDataSourceConfig {
    
        // 注入数据源配置
        @Primary
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.test-mysql")
        public DataSourceProperties mysqlDataSourceProperties() {
            return new DataSourceProperties();
        }
    
        // 创建数据库连接
        @Primary
        @Bean
        public DataSource mysqlDataSource() {
            return mysqlDataSourceProperties().initializeDataSourceBuilder().build();
        }
    
        // 创建session工厂
        @Primary
        @Bean
        public SqlSessionFactory mysqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(
                    new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
            return sessionFactoryBean.getObject();
        }
    
        // 创建事务管理(按需添加)
        @Primary
        @Bean
        public DataSourceTransactionManager mysqlDataSourceTransactionManager() {
            return new DataSourceTransactionManager(mysqlDataSource());
        }
    
        // 会话管理
        @Primary
        @Bean
        public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }
    

    次数据源(sqlserver)  

    package com.zhangyu.springboot.multidatasource.config;
    
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
    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 org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import tk.mybatis.spring.annotation.MapperScan;
    
    import javax.sql.DataSource;
    
    // sqlserver数据源配置
    @Configuration
    @MapperScan(basePackages = "com.zhangyu.springboot.multidatasource.mapper.sqlserver", sqlSessionTemplateRef = "sqlServerSqlSessionTemplate")
    public class TestSqlServerDataSourceConfig {
    
        // 注入数据源配置
        @Bean
        @ConfigurationProperties(prefix = "spring.datasource.test-sqlserver")
        public DataSourceProperties sqlServerDataSourceProperties() {
            return new DataSourceProperties();
        }
    
    
        // 创建数据库连接
        @Bean
        public DataSource sqlServerDataSource() {
            return sqlServerDataSourceProperties().initializeDataSourceBuilder().build();
        }
    
        // 创建session工厂
        @Bean
        public SqlSessionFactory sqlServerSessionFactory(@Qualifier("sqlServerDataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(
                    new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
            return sessionFactoryBean.getObject();
        }
    
        // 创建事务管理(按需添加)
        @Bean
        public DataSourceTransactionManager sqlServerDataSourceTransactionManager() {
            return new DataSourceTransactionManager(sqlServerDataSource());
        }
    
        // 会话管理
        @Bean
        public SqlSessionTemplate sqlServerSqlSessionTemplate(@Qualifier("sqlServerSessionFactory") SqlSessionFactory sqlSessionFactory) {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }
    

        再啰嗦几句,mybatis是通过配置的扫描包和对应的sqlSessionTemplate来自动切换数据源,即通过在 @MapperScan 注解中配置 basePackagessqlSessionTemplateRef。

    四、尾声

        启动项目,可以看到控制台打印如下信息:

    INFO 12840 --- [)-26.12.195.117] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
    INFO 12840 --- [)-26.12.195.117] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
    INFO 12840 --- [)-26.12.195.117] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
    INFO 12840 --- [)-26.12.195.117] com.zaxxer.hikari.pool.PoolBase          : HikariPool-2 - Driver does not support get/set network timeout for connections. (null)
    INFO 12840 --- [)-26.12.195.117] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
    

        很明显实例化了两个 HikariPool ,实际使用又如何呢?

      Usermapper连接的mysql数据库,TestMapper连接的sqlserver数据库:

    //Service:

    public List<TbUser> getUserList() { return userMapper.selectAll(); } public List<Test> getTestList() { return testMapper.selectAll(); }

        分别调用,能都正常获取数据。

        至此,springboot双数据源配置完成,tk-mybatis也能正常使用。

     ********************************************************************************************************************************************************************

                                                                                                       打完收工

     ********************************************************************************************************************************************************************

     

  • 相关阅读:
    servlet
    grep命令
    sort排序命令
    shell脚本面试
    查看远端的端口是否通畅3个简单实用案例!
    mail命令
    linux系统优化的方法
    shell数组
    shell函数介绍语法说明及基本例子
    循环结构的多个控制命令对比与实际案例
  • 原文地址:https://www.cnblogs.com/little-rain/p/13395208.html
Copyright © 2020-2023  润新知