• 多数据源+数据库分库分表


    shardingjdbc+dynamic-datasource


    为了实现 多数据源+数据分库分表

    多数据源采用 mybatis-plus的dynamic-datasource

    分库分表采用sharding-jdbc

    项目使用springboot搭建,junit测试,为了方便实现对数据库操作继承了Jpa,为了少些get、set 引入lombok

    1、搭建项目

    使用idea新建Springboot项目,此处我的依赖为

    
            1.8
            UTF-8
            UTF-8
            2.3.7.RELEASE
    
        
    
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
    
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            mysql
            mysql-connector-java
            runtime
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
            
            org.junit.vintage
            junit-vintage-engine
            
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2、集成jpa

    上面的操作已经将jpa依赖引入,接下来需要配置jpa,以及建立数据库,目标是先集成jpa完成数据的增删改查(增查即可)

    2.1、修改配置文件

    修改application.yml配置文件(可将配置修改为此后缀),并增加jpa配置(下文配置文件可能存在缩进问题,注意修改)

    spring:
        datasource:
            url: jdbc:mysql://localhost:3306/authsso?serverTimezone=UTC
            username: root
            password: root
            driver-class-name: com.mysql.cj.jdbc.Driver
        jpa:
            hibernate:
            ## 此处后期需要修改 改为 none,此处先使用create
                ddl-auto: create
            ## 是否启用SQL语句日志记录。
            show-sql: true
            ## 要操作的目标数据库的名称,默认情况下是自动检测的。也可以使用“Database”enum进行设置。
            database-platform:
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    此处我使用的是本地数据库(mysql8 注意驱动),在本地新建authsso数据库,使用命令或可视化工具,表的新建将会由jpa完成

    2.2、新建实体以及dao层

    在启动类目录下新建package entitydao,并新建 User.class与UserDao(主键皆为自增且为bigint类型),如下所示(JPA用法不做详细赘述,可自行参考文档学习,此处仅为快速使用)

    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * @author Administrator
     */
    @Entity
    @Table(name = "sys_user")
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public class User implements Serializable {
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name = "user_id")
        private Long userId;
        @Column(name = "phone", length = 16)
        private String phone;
        @Column(name = "name", length = 50)
        private String name;
        @Column(name = "nick_name", length = 50)
        private String nickName;
        @Column(name = "create_user_id")
        private Long createUserId;
        @Column(name = "update_user_id")
        private Long updateUserId;
        @Column(name = "create_time")
        private Date createTime;
        @Column(name = "update_time")
        private Date updateTime;
        @Column(name = "statu", length = 2)
        private Integer status;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    import com.example.dunamic.entity.User;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public interface UserDao extends JpaRepository<User, Long> {
        List<User> findAllByName(String name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.3、编写测试类

    使用junit进行测试,代码如下所示,编写完成后数据成功入库

    import com.example.dunamic.dao.UserDao;
    import com.example.dunamic.entity.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.Date;
    import java.util.LinkedList;
    import java.util.List;
    
    @SpringBootTest
    class DunamicApplicationTests {
    
        @Autowired
        private UserDao userDao;
    
        @Test
        void contextLoads() {
    
            List<User> testSave = new LinkedList<>();
    
            for (int i = 0; i < 1000; i++) {
                testSave.add(User
                        .builder()
                        .name("罗翔-张三" + i)
                        .nickName("张三" + i)
                        .phone("15711300994" + i)
                        .createTime(new Date())
                        .createUserId(1L)
                        .status(1)
                        .build());
            }
    
            userDao.saveAll(testSave);
    
            List<User> userInfo = userDao.findAllByName("罗翔-张三");
            for (User user : userInfo) {
                System.out.println(user);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    3、集成shardingjdbc

    3.1、pom引入依赖

    
    
        org.apache.shardingsphere
        sharding-jdbc-spring-boot-starter
        4.1.1
    
    
        com.alibaba
        druid
        1.2.11
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3.2、修改配置文件

    修改application.yml配置文件

    spring:
        shardingsphere:
            datasource:
                #数据源名称,多数据源以逗号分隔
                names: db0
                db0:
                  type: com.alibaba.druid.pool.DruidDataSource
                  #数据库驱动类名
                  driver-class-name: com.mysql.cj.jdbc.Driver
                  #数据库url连接
                  url: jdbc:mysql://localhost:3306/authsso?serverTimezone=UTC
                  #数据库用户名
                  username: root
                  #数据库密码
                  password: root
            sharding:
                tables:
                    # sys_user 分表
                    sys_user:
                        # 真实表名 sys_user_0 sys_user_1
                      actual-data-nodes: db0.sys_user_$->{0..9}
                      # 分表策略
                      table-strategy:
                          inline:
                              # 根据此列进行分表
                            sharding-column: user_id
                            algorithm-expression: sys_user_$->{user_id % 10}
                      key-generator:
                          # 主键字段
                        column: user_id
                        # 主键生成策略
                        type: SNOWFLAKE
    
        jpa:
            hibernate:
            ## 此处修改为none
                ddl-auto: none
            ## 是否启用SQL语句日志记录。
            show-sql: true
            ## 要操作的目标数据库的名称,默认情况下是自动检测的。也可以使用“Database”enum进行设置。
            database-platform:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    3.3、在数据库新建表

    sys_user_0 -> sys_user_10 注意和配置文件相匹配

    3.4、测试

    此时已经完成了单库分表配置,直接运行单元测试向表中插入数据,可以看到 sys_user_0 -> sys_user_10 11个表均有数据

    4、集成dynamic-datasource

    4.1、pom引入依赖集成多数据源

    
        com.baomidou
        dynamic-datasource-spring-boot-starter
        3.5.1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.2、增加配置

    4.2.1、增加配置文件配置

    此时需要新建数据库cloud_auth并新建表sys_org,用以测试多数据源

    spring:
        application:
            name: dunamic
        datasource:
          dynamic:
            primary: master
            datasource:
              master:
                url: jdbc:mysql://localhost:3306/cloud_auth?serverTimezone=UTC
                username: root
                password: root
                driver-class-name: com.mysql.cj.jdbc.Driver
        shardingsphere:
            datasource:
                #数据源名称,多数据源以逗号分隔
                names: db0
                db0:
                  type: com.alibaba.druid.pool.DruidDataSource
                  #数据库驱动类名
                  driver-class-name: com.mysql.cj.jdbc.Driver
                  #数据库url连接
                  url: jdbc:mysql://localhost:3306/authsso?serverTimezone=UTC
                  #数据库用户名
                  username: root
                  #数据库密码
                  password: root
            sharding:
                tables:
                    # sys_user 分表
                    sys_user:
                        # 真实表名 sys_user_0 sys_user_1
                      actual-data-nodes: db0.sys_user_$->{0..9}
                      # 分表策略
                      table-strategy:
                          inline:
                              # 根据此列进行分表
                            sharding-column: user_id
                            algorithm-expression: sys_user_$->{user_id % 10}
                      key-generator:
                          # 主键字段
                        column: user_id
                        # 主键生成策略
                        type: SNOWFLAKE
    
        jpa:
            hibernate:
                ddl-auto: none
            ## 是否启用SQL语句日志记录。
            show-sql: true
            ## 要操作的目标数据库的名称,默认情况下是自动检测的。也可以使用“Database”enum进行设置。
            database-platform:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    4.2.2、 新建数据库以及表

    新建cloud_auth数据库,并执行以下sql新建表

    CREATE TABLE `sys_org`  (
      `org_id` bigint(0) NOT NULL AUTO_INCREMENT,
      `create_time` datetime(6) NULL DEFAULT NULL,
      `create_user_id` bigint(0) NULL DEFAULT NULL,
      `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
      `statu` int(0) NULL DEFAULT NULL,
      `update_time` datetime(6) NULL DEFAULT NULL,
      `update_user_id` bigint(0) NULL DEFAULT NULL,
      PRIMARY KEY (`org_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.2.3、增加java代码配置

    新建entity以及dao,代码如下
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import javax.persistence.*;
    import java.util.Date;
    
    @Entity
    @Table(name = "sys_org")
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public class Org {
    
        @Id
        @GeneratedValue(strategy= GenerationType.IDENTITY)
        @Column(name = "org_id")
        private Long orgId;
        @Column(name = "name", length = 50)
        private String name;
    
    
        @Column(name = "create_user_id")
        private Long createUserId;
        @Column(name = "update_user_id")
        private Long updateUserId;
        @Column(name = "create_time")
        private Date createTime;
        @Column(name = "update_time")
        private Date updateTime;
        @Column(name = "statu", length = 2)
        private Integer status;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    import com.example.dunamic.entity.Org;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface OrgDao extends JpaRepository<Org, Long> {
    
        Org findByOrgId(Long orgId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    修改原UserDao
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.example.dunamic.entity.User;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    // 增加此配置,以标记此处使用分库分表 shardingjdbc管理的数据源
    @DS("sharding_db")
    public interface UserDao extends JpaRepository<User, Long> {
    
        List<User> findAllByName(String name);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    新建配置文件

    在启动类所在包下新建configpackage,并新建DataSourceConfiguration.class

    package com.example.dunamic.config;
    
    
    import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
    import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
    import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
    import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
    import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
    import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
    import org.apache.shardingsphere.shardingjdbc.jdbc.adapter.AbstractDataSourceAdapter;
    import org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.context.annotation.Primary;
    
    import javax.annotation.Resource;
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    @AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class,
            SpringBootConfiguration.class})
    public class DataSourceConfiguration {
    
        /**
         * 分表数据源名称
         */
        private static final String SHARDING_DATA_SOURCE_NAME = "sharding_db";
    
        @Lazy
        @Resource(name = "shardingDataSource")
        AbstractDataSourceAdapter shardingDataSource;
    
        @Autowired
        private DynamicDataSourceProperties properties;
    
        @Bean
        public DynamicDataSourceProvider dynamicDataSourceProvider() {
            Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
            return new AbstractDataSourceProvider() {
                @Override
                public Map<String, DataSource> loadDataSources() {
                    Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                    // 将 shardingjdbc 管理的数据源也交给动态数据源管理
                    dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingDataSource);
                    return dataSourceMap;
                }
            };
        }
        
    	@Primary
        @Bean
        public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
            DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
            dataSource.setPrimary(properties.getPrimary());
            dataSource.setStrict(properties.getStrict());
            dataSource.setStrategy(properties.getStrategy());
            dataSource.setP6spy(properties.getP6spy());
            dataSource.setSeata(properties.getSeata());
            return dataSource;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    测试
     @Autowired
        private UserDao userDao;
    
        @Autowired
        private OrgDao orgDao;
    
        @Test
        void contextLoads() {
    
            List<User> testSave = new LinkedList<>();
    
    
            for (int i = 0; i < 1000; i++) {
                testSave.add(User
                        .builder()
                        .name("罗翔-张三" + i)
                        .nickName("张三" + i)
                        .phone("15711300994" + i)
                        .createTime(new Date())
                        .createUserId(1L)
                        .status(1)
                        .build());
            }
    
    
            userDao.saveAll(testSave);
    
            List<User> userInfo = userDao.findAllByName("罗翔-张三");
            for (User user : userInfo) {
                System.out.println(user);
            }
    
    
            orgDao.save(Org
                    .builder()
                    .name("罗三")
                    .createTime(new Date())
                    .createUserId(1L)
                    .status(1)
                    .build());
            Org orgInfo = orgDao.findByOrgId(1l);
            System.out.println(orgInfo);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    参考文档

  • 相关阅读:
    mysql的索引语法
    Spring @Transactional事务管理
    一些常用的画图网站,以及一些经常听说但不太常用的图形模版
    Dockerfile实例及应用场景
    (论文翻译)UFO: Unified Feature Optimization——UFO:统一特性优化
    高性能日志脱敏组件:已支持 log4j2 和 logback 插件
    掌握Java并发编程线程池的实现原理
    开创性的区块链操作系统项目——生物识别与机器学习
    9月,1Panel开源面板项目收到了这些评论
    批量提取文件名到excel?
  • 原文地址:https://blog.csdn.net/qq_37681291/article/details/126034844