接上一篇博客,实现了SpringBoot+mybatis-plus+sharding-jdbc+druid 分表, 这一篇可以支持多个库动态切换分表操作。
(1)代码结构
(2)pom文件
cqx-test
cqx-test
0.0.1
4.0.0
SpringBootShareMutilDB
org.springframework.boot
spring-boot-starter
2.0.2.RELEASE
org.springframework.boot
spring-boot-starter-web
2.0.2.RELEASE
org.springframework.boot
spring-boot-starter-test
2.0.2.RELEASE
test
org.springframework.boot
spring-boot-starter-jdbc
2.0.2.RELEASE
org.projectlombok
lombok
1.16.18
provided
mysql
mysql-connector-java
5.1.46
com.baomidou
mybatis-plus-boot-starter
3.4.1
spring-boot-starter-jdbc
org.springframework.boot
com.baomidou
dynamic-datasource-spring-boot-starter
3.3.2
org.apache.shardingsphere
sharding-jdbc-spring-boot-starter
4.1.1
org.apache.shardingsphere
sharding-jdbc-spring-namespace
4.1.1
com.baomidou
mybatis-plus-generator
3.4.1
org.apache.velocity
velocity-engine-core
2.2
com.alibaba
druid-spring-boot-starter
1.1.10
com.alibaba
druid
1.2.4
net.coobird
thumbnailator
0.4.8
com.google.code.gson
gson
2.8.6
commons-io
commons-io
2.4
com.google.guava
guava
18.0
(3)application.yaml
server:
port : 18997
spring:
shardingsphere:
props:
sql.show: false
datasource:
# 可以配置多个库
names: db1,db2
db1:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sharedb?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
username: root
password: root@123
db2:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sharedb2?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
username: root
password: root@123
sharding:
tables:
share_user:
actualDataNodes: db1.share_user_$->{0..2}
tableStrategy:
inline:
# 指定分片键
shardingColumn: user_id
# 分片算法
algorithmExpression: share_user_$->{user_id % 3}
my_user:
actualDataNodes: db2.my_user_$->{0..1}
tableStrategy:
inline:
# 指定分片键
shardingColumn: user_id
# 分片算法
algorithmExpression: my_user_$->{user_id % 2}
datasource:
dynamic:
primary: db1 #设置默认的数据源或者数据源组,默认值即为db1
strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
druid: #以下均为默认值
initial-size: 4
max-active: 50
min-idle: 5
max-wait: -1
min-evictable-idle-time-millis: 30000
max-evictable-idle-time-millis: 30000
time-between-eviction-runs-millis: 0
validation-query: select 1
validation-query-timeout: -1
test-on-borrow: false
test-on-return: false
test-while-idle: true
pool-prepared-statements: true
filters: stat,wall
share-prepared-statements: true
datasource:
db1:
url: jdbc:mysql://127.0.0.1:3306/sharedb?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
username: root
password: root@123
db2:
url: jdbc:mysql://127.0.0.1:3306/sharedb2?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT
username: root
password: root@123
(4)代码
1、MysqlGenerator.java
package com.cqx.spring.sharemutildb;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.apache.commons.lang3.StringUtils;
import java.util.Scanner;
/**
*
* mysql 代码生成器演示例子
*
*
* @author jobob
* @since 2018-09-12
*/
public class MysqlGenerator {
/**
*
* 读取控制台内容
*
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入").append(tip).append(":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
/**
* RUN THIS
*/
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/SpringBootShareDB/src/main/java");//自己的目录
gc.setAuthor("mybatisPlusGenerator");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
// dsc.setUrl("jdbc:mysql://127.0.0.1:3306/sharedb?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT");
// dsc.setDriverName("com.mysql.jdbc.Driver");
// dsc.setUsername("root");
// dsc.setPassword("root@123");
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/sharedb2?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimezone=GMT");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root@123");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.cqx.spring.sharedb.mybatis");
mpg.setPackageInfo(pc);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setController("");
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setRestControllerStyle(true);
strategy.setEntityLombokModel(true);
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setInclude(scanner("表名"));
mpg.setStrategy(strategy);
mpg.execute();
}
}
2、ShareMutilDBApplication.java
package com.cqx.spring.sharemutildb;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@MapperScan("com.cqx.spring.sharemutildb.mybatis.mapper")
public class ShareMutilDBApplication {
public static void main(String[] args) {
SpringApplication.run(ShareMutilDBApplication.class, args);
}
}
3、ShareMutilDbDataSourceConfig.java 这个就是将shardingDataScource整合到dynamic中的最重要的配置
package com.cqx.spring.sharemutildb.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.spring.boot.SpringBootConfiguration;
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;
/**
* @author chaiqx on 2022/2/17
*/
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class ShareMutilDbDataSourceConfig {
@Resource
private DynamicDataSourceProperties properties;
@Lazy
@Resource(name = "shardingDataSource") //shardingSphereDataSource
private DataSource shardingSphereDataSource;
// @Resource(name = "masterSlaveDataSource")
// private DataSource masterSlaveDataSource;
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
Map datasourceMap = properties.getDatasource();
return new AbstractDataSourceProvider() {
@Override
public Map loadDataSources() {
Map dataSourceMap = createDataSourceMap(datasourceMap);
dataSourceMap.put("sharding", shardingSphereDataSource);
//打开下面的代码可以把 shardingjdbc 管理的数据源也交给动态数据源管理 (根据自己需要选择开启)
// dataSourceMap.putAll(((MasterSlaveDataSource) masterSlaveDataSource).getDataSourceMap());
return dataSourceMap;
}
};
}
/**
* 将动态数据源设置为首选的
* 当spring存在多个数据源时, 自动注入的是首选的对象
* 设置为主要的数据源之后,就可以支持shardingjdbc原生的配置方式了
*/
@Primary
@Bean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
}
4、TestSpringShareDBController.java
package com.cqx.spring.sharemutildb.ctrl;
import com.cqx.spring.sharemutildb.mybatis.entity.MyUser;
import com.cqx.spring.sharemutildb.mybatis.entity.ShareUser;
import com.cqx.spring.sharemutildb.mybatis.service.IMyUserService;
import com.cqx.spring.sharemutildb.mybatis.service.IShareUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author chaiqx on 2021/3/30
*/
@RestController
public class TestSpringShareDBController {
@Autowired
private IShareUserService shareUserService;
@Autowired
private IMyUserService myUserService;
@GetMapping(value = "share_user")
public int test_share_user() {
ShareUser shareUser1 = new ShareUser();
shareUser1.setUserId(5);
shareUser1.setName("5");
ShareUser shareUser2 = new ShareUser();
shareUser2.setUserId(6);
shareUser2.setName("6");
ShareUser shareUser3 = new ShareUser();
shareUser3.setUserId(7);
shareUser3.setName("7");
ShareUser shareUser4 = new ShareUser();
shareUser4.setUserId(8);
shareUser4.setName("8");
shareUserService.save(shareUser1);
shareUserService.save(shareUser2);
shareUserService.save(shareUser3);
shareUserService.save(shareUser4);
MyUser myUser1 = new MyUser();
myUser1.setUserId(5);
myUser1.setName("5");
MyUser myUser2 = new MyUser();
myUser2.setUserId(6);
myUser2.setName("6");
MyUser myUser3 = new MyUser();
myUser3.setUserId(7);
myUser3.setName("7");
MyUser myUser4 = new MyUser();
myUser4.setUserId(8);
myUser4.setName("8");
myUserService.save(myUser1);
myUserService.save(myUser2);
myUserService.save(myUser3);
myUserService.save(myUser4);
return 1;
}
@GetMapping(value = "get_user")
public int test_get_user() {
System.out.println(shareUserService.list().size());
System.out.println(myUserService.list().size());
return 1;
}
}
5、自动生成的代码就不累赘了。但是需要注意两个地方:MyUserServiceImpl.java 和 ShareUserServiceImpl.java
package com.cqx.spring.sharemutildb.mybatis.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqx.spring.sharemutildb.mybatis.entity.MyUser;
import com.cqx.spring.sharemutildb.mybatis.mapper.MyUserMapper;
import com.cqx.spring.sharemutildb.mybatis.service.IMyUserService;
import org.springframework.stereotype.Service;
/**
*
* 服务实现类
*
*
* @author mybatisPlusGenerator
* @since 2022-02-17
*/
@Service
@DS("sharding")//这个是必须要加的,就是config配置的那个
public class MyUserServiceImpl extends ServiceImpl implements IMyUserService {
}
package com.cqx.spring.sharemutildb.mybatis.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqx.spring.sharemutildb.mybatis.entity.ShareUser;
import com.cqx.spring.sharemutildb.mybatis.mapper.ShareUserMapper;
import com.cqx.spring.sharemutildb.mybatis.service.IShareUserService;
import org.springframework.stereotype.Service;
/**
*
* 服务实现类
*
*
* @author mybatisPlusGenerator
* @since 2022-02-17
*/
@Service
@DS("sharding")
public class ShareUserServiceImpl extends ServiceImpl implements IShareUserService {
}
(5)数据库和表 (都只包含id自增,user_id(int11),name(varchar30))