shardingjdbc+dynamic-datasource
文章目录
为了实现 多数据源+数据分库分表
多数据源采用 mybatis-plus的dynamic-datasource
分库分表采用sharding-jdbc
项目使用springboot搭建,junit测试,为了方便实现对数据库操作继承了Jpa,为了少些get、set 引入lombok
1、搭建项目
使用idea新建Springboot项目,此处我的依赖为
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
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 entity
与dao
,并新建 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引入依赖
<!-- for spring boot -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
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引入依赖集成多数据源
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
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);
}
新建配置文件
在启动类所在包下新建config
package,并新建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);
}
参考文档
版权声明:本文为qq_37681291原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。