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

shardingjdbc+dynamic-datasource

文章目录

  • shardingjdbc+dynamic-datasource
    • 1、搭建项目
    • 2、集成jpa
      • 2.1、修改配置文件
      • 2.2、新建实体以及dao层
      • 2.3、编写测试类
    • 3、集成shardingjdbc
      • 3.1、pom引入依赖
      • 3.2、修改配置文件
      • 3.3、在数据库新建表
      • 3.4、测试
    • 4、集成dynamic-datasource
      • 4.1、pom引入依赖集成多数据源
      • 4.2、增加配置
        • 4.2.1、增加配置文件配置
        • 4.2.2、 新建数据库以及表
        • 4.2.3、增加java代码配置
          • 新建entity以及dao,代码如下
          • 修改原UserDao
          • 新建配置文件
          • 测试
  • 参考文档

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

多数据源采用 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
        
        
    

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:

此处我使用的是本地数据库(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;
}
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);
}

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);
        }
    }
}

3、集成shardingjdbc

3.1、pom引入依赖



    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.1.1


    com.alibaba
    druid
    1.2.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:

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

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:
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;
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;
}

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);
}

修改原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);
}

新建配置文件

在启动类所在包下新建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;
    }

}
测试
 @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);
    }

参考文档

  • 官方文档
  • sharding-jdbc配置手册

你可能感兴趣的:(java,数据库,mybatis,java)