日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分库分表之_分库分表 + 复杂查询

發(fā)布時間:2024/1/1 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分库分表之_分库分表 + 复杂查询 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

代碼配置暫時和和分庫分表之_分庫分表相同。但是為了測試下面的join查詢將user表的數(shù)量調(diào)整到了和company表的數(shù)量一致,以及給company添加了一個新的字段ref_user_id

1、開始Demo

1.1、hlj-08-sharding_db_table-range_group.sql

drop database if exists ds_0; create database ds_0 character set 'utf8' collate 'utf8_general_ci'; use ds_0;drop table if exists user_0; create table `user_0` (id bigint(20) unsigned not null,city varchar(20) not null default '',name varchar(20) not null default '',age int(11) not null default 0,status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;drop table if exists user_1; create table `user_1` (id bigint(20) unsigned not null,city varchar(20) not null default '',name varchar(20) not null default '',age int(11) not null default 0,status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;drop table if exists company_0; create table `company_0` (id bigint(20) unsigned not null comment '主鍵',ref_user_id bigint(20) unsigned not null comment '主鍵',name varchar(20) not null default '' comment '企業(yè)名稱',company_name_english varchar(128) not null default '' comment '企業(yè)英文名稱',status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;drop table if exists company_1; create table `company_1` (id bigint(20) unsigned not null comment '主鍵',ref_user_id bigint(20) unsigned not null comment '主鍵',name varchar(20) not null default '' comment '企業(yè)名稱',company_name_english varchar(128) not null default '' comment '企業(yè)英文名稱',status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;CREATE TABLE `demo_entity` (id bigint(20) unsigned NOT NULL COMMENT '主鍵',`name` varchar(64) NOT NULL,`phone` varchar(20) DEFAULT '' COMMENT '手機(jī)號',`email` varchar(64) DEFAULT '' COMMENT '郵箱',`age` int(10) DEFAULT NULL,`status` varchar(8) NOT NULL COMMENT '狀態(tài)',`create_user` bigint(16) unsigned DEFAULT NULL COMMENT '創(chuàng)建人',`create_name` varchar(64) DEFAULT '' COMMENT '創(chuàng)建人名稱',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',`update_user` bigint(16) unsigned DEFAULT NULL COMMENT '更新人',`update_name` varchar(64) DEFAULT '' COMMENT '更新人名稱',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',PRIMARY KEY (id) ) ENGINE = InnoDBDEFAULT CHARSET = utf8;drop database if exists ds_1; create database ds_1 character set 'utf8' collate 'utf8_general_ci'; use ds_1;drop table if exists user_0; create table `user_0` (id bigint(20) unsigned not null,city varchar(20) not null default '',name varchar(20) not null default '',age int(11) not null default 0,status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;drop table if exists user_1; create table `user_1` (id bigint(20) unsigned not null,city varchar(20) not null default '',name varchar(20) not null default '',age int(11) not null default 0,status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;drop table if exists company_0; create table `company_0` (id bigint(20) unsigned not null comment '主鍵',ref_user_id bigint(20) unsigned not null comment '主鍵',name varchar(20) not null default '' comment '企業(yè)名稱',company_name_english varchar(128) not null default '' comment '企業(yè)英文名稱',status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;drop table if exists company_1; create table `company_1` (id bigint(20) unsigned not null comment '主鍵',ref_user_id bigint(20) unsigned not null comment '主鍵',name varchar(20) not null default '' comment '企業(yè)名稱',company_name_english varchar(128) not null default '' comment '企業(yè)英文名稱',status int(10) not null default '0' comment '狀態(tài)',create_time datetime not null default current_timestamp comment '創(chuàng)建時間',update_time datetime not null default current_timestamp on update current_timestamp comment '修改時間',primary key (id) ) engine = innodbdefault charset = utf8;

1.1.1、數(shù)據(jù)庫圖文

1.2、依賴

<!--shardingsphere--> <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1</version> </dependency>

1.3、配置文件:application.properties

server.port=8888# 配置 mybatis的一些配置,也可以在 application.properties 中配置,如果配置了就不需要了mybatis.xml #mybatis-plus.config-location=classpath:mybatis.xml #Maven 多模塊項目的掃描路徑需以 classpath*: 開頭 (即加載多個 jar 包下的 XML 文件) mybatis-plus.mapper-locations=classpath*:mapper/*.xml mybatis-plus.type-aliases-package=com.healerjean.proj.pojo ##主鍵類型 0:"數(shù)據(jù)庫ID自增,非常大", 1:"用戶輸入ID(如果用戶不輸入,則默認(rèn)是0)",2:"全局唯一ID (數(shù)字類型唯一ID)", 3:"全局唯一ID UUID"; mybatis-plus.id-type: 0 #字段策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷" mybatis-plus.field-strategy: 2 #數(shù)據(jù)庫大寫下劃線轉(zhuǎn)換 mybatis-plus.capital-mode: true mybatis-plus.refresh-mapper: true# #當(dāng)遇到同樣名字的時候,是否允許覆蓋注冊 spring.main.allow-bean-definition-overriding=true # 顯示SQL spring.shardingsphere.props.sql.show=true############################## ## 分庫分表 ############################# spring.shardingsphere.datasource.names=ds0,ds1# 數(shù)據(jù)源 spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver spring.shardingsphere.datasource.ds0.url=jdbc:mysql://localhost:3306/ds_0?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true spring.shardingsphere.datasource.ds0.username=root spring.shardingsphere.datasource.ds0.password=123456spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localhost:3306/ds_1?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true spring.shardingsphere.datasource.ds1.username=root spring.shardingsphere.datasource.ds1.password=123456# 分庫配置 #spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=id #spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{id % 2} spring.shardingsphere.sharding.default-database-strategy.standard.sharding-column=id spring.shardingsphere.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.healerjean.proj.config.datasource.CustomShardingDBAlgorithm# user company 分表 # user_0,user_1,user_2(自定義分表算法) spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..1} spring.shardingsphere.sharding.tables.user.table-strategy.standard.sharding-column=id spring.shardingsphere.sharding.tables.user.table-strategy.standard.precise-algorithm-class-name=com.healerjean.proj.config.datasource.CustomShardingTableAlgorithm # company_0,company_1 (inline分表策略 表達(dá)式 id%2) spring.shardingsphere.sharding.tables.company.actual-data-nodes=ds$->{0..1}.company_$->{0..1} spring.shardingsphere.sharding.tables.company.database-strategy.inline.sharding-column=ref_user_id spring.shardingsphere.sharding.tables.company.database-strategy.inline.algorithm-expression=ds${ref_user_id.longValue() % 2} spring.shardingsphere.sharding.tables.company.table-strategy.inline.sharding-column=ref_user_id spring.shardingsphere.sharding.tables.company.table-strategy.inline.algorithm-expression=company_${ref_user_id.longValue() % 2}## 默認(rèn)數(shù)據(jù)源指定(不分庫的表) spring.shardingsphere.sharding.default-data-source-name=ds0

1.4、具體測試方法和類

1.4.1、實體類

1.4.1.1、User.java

@Data @Accessors(chain = true) public class User implements Serializable {private static final long serialVersionUID = 1L;/** 主鍵 */private Long id;private String name;private String city;private Integer age;private String status;private Date createTime;private Date updateTime; }

1.4.1.2、Company.java

@Data public class Company {private Long id;private Long refUserId;private String name;private String companyNameEnglish;private String status;private Date createTime;private Date updateTime; }

1.4.1.3、DemoEntity.java

@Data @Accessors(chain = true) public class DemoEntity implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String name;private String phone;private String email;private Integer age;private String status;private Long createUser;private String createName;private java.util.Date createTime;private Long updateUser;private String updateName;private java.util.Date updateTime;}

1.4.1.4、新對象 UserRefCompany

@Data public class UserRefCompany {/** 主鍵 */private Long userId;private String name;private String city;private String status;private Long companyId;private String companyName;private String companyNameEnglish;private Integer avgAge;private Integer sumAge;}

1.4.2、DTO數(shù)據(jù)

1.4.2.1、UserDTO.java

@Data @Accessors(chain = true) @ApiModel(value = "demo實體類") @JsonInclude(JsonInclude.Include.NON_NULL) public class UserDTO {@ApiModelProperty(value = "主鍵", hidden = true)@JsonSerialize(using = JsonLongSerializer.class )private Long id;@ApiModelProperty(value = "姓名")@NotBlank(message = "姓名不能為空", groups = ValidateGroup.HealerJean.class)private String name;@ApiModelProperty(value = "城市")private String city;@ApiModelProperty(value = "年齡")private Integer age;@ApiModelProperty(value = "狀態(tài)", hidden = true)private String status;@ApiModelProperty(value = "創(chuàng)建時間", hidden = true)@JsonFormat(pattern = DateUtils.YYYY_MM_dd_HH_mm_ss, timezone = "GMT+8")private Date createTime;@ApiModelProperty(value = "修改時間", hidden = true)@JsonFormat(pattern = DateUtils.YYYY_MM_dd_HH_mm_ss, timezone = "GMT+8")private Date updateTime;private Integer pageNow ;private Integer pageSize ;}

1.4.2.2、CompanyDTO.java

@Data public class CompanyDTO {@JsonSerialize(using = JsonLongSerializer.class)private Long id;private Long refUserId;private String name;private String companyNameEnglish;private String status;@ApiModelProperty(value = "創(chuàng)建時間", hidden = true)@JsonFormat(pattern = DateUtils.YYYY_MM_dd_HH_mm_ss, timezone = "GMT+8")private Date createTime;@ApiModelProperty(value = "修改時間", hidden = true)@JsonFormat(pattern = DateUtils.YYYY_MM_dd_HH_mm_ss, timezone = "GMT+8")private Date updateTime; }

1.4.2.3、DemoDTO.java

@Data @Accessors(chain = true) @ApiModel(value = "demo實體類") @JsonInclude(JsonInclude.Include.NON_NULL) public class DemoDTO extends PageQuery {@JsonSerialize(using = JsonLongSerializer.class )private Long id;@ApiModelProperty(value = "姓名")@NotBlank(message = "姓名不能為空", groups = ValidateGroup.HealerJean.class)private String name;@ApiModelProperty(value = "年齡")private Integer age;@ApiModelProperty(value = "手機(jī)號")private String phone;@ApiModelProperty(value = "郵箱")private String email;@ApiModelProperty(value = "是否刪除,10可用,99刪除 ", hidden = true)private String status;@ApiModelProperty(value = "創(chuàng)建人", hidden = true)private Long createUser;@ApiModelProperty(value = "創(chuàng)建人名字", hidden = true)private String createName;@ApiModelProperty(value = "創(chuàng)建時間", hidden = true)private java.util.Date createTime;@ApiModelProperty(value = "更新人", hidden = true)private Long updateUser;@ApiModelProperty(value = "更新人名稱", hidden = true)private String updateName;@ApiModelProperty(hidden = true)private java.util.Date updateTime;}

1.4.3、Mapper

1.4.3.1、UserMapper.java

public interface UserMapper extends BaseMapper<User> {}

1.4.3.1、CompanyMapper.java

public interface CompanyMapper extends BaseMapper<Company> {}

1.4.3.1、DemoEntityMapper.java

public interface DemoEntityMapper extends BaseMapper<DemoEntity> {}

1.4.4、Service

1.4.4.1、 UserService.java

public interface UserService {UserDTO insert(UserDTO userDTO);UserDTO findById(Long id);List<UserDTO> list();}

1.4.4.2、 CompanyService.java

public interface CompanyService {CompanyDTO insert(CompanyDTO companyDTO);CompanyDTO findById(Long id);List<CompanyDTO> list(); }

1.4.4.3、 DemoEntityService.java

public interface DemoEntityService {DemoDTO insert(DemoDTO demoEntity);DemoDTO findById(Long id);List<DemoDTO> list();}

1.4.5、ServiceImpl.java

1.4.5.1、UserServiceImpl.java

@Service @Slf4j public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Overridepublic UserDTO insert(UserDTO userDTO) {User user = BeanUtils.dtoToUserDTO(userDTO);user.setStatus(StatusEnum.生效.code);userMapper.insert(user);userDTO.setId(user.getId());return userDTO;}@Overridepublic UserDTO findById(Long id) {User user = userMapper.selectById(id);return user == null ? null : BeanUtils.userToDTO(user);}@Overridepublic List<UserDTO> list() {List<User> users = userMapper.selectList(null);List<UserDTO> list = null;if (!EmptyUtil.isEmpty(users)) {list = users.stream().map(BeanUtils::userToDTO).collect(Collectors.toList());}return list;}}

1.4.5.2、CompanyServiceImpl.java

@Service public class CompanyServiceImpl implements CompanyService {@Resourceprivate CompanyMapper companyMapper;@Overridepublic CompanyDTO insert(CompanyDTO companyDTO) {Company company = BeanUtils.dtoToCompany(companyDTO);company.setStatus(StatusEnum.生效.code);companyMapper.insert(company);companyDTO.setId(company.getId());return companyDTO;}@Overridepublic CompanyDTO findById(Long id) {Company company = companyMapper.selectById(id);return company == null ? null : BeanUtils.companyToDTO(company);}@Overridepublic List<CompanyDTO> list() {List<Company> companys = companyMapper.selectList(null);List<CompanyDTO> list = null;if (!EmptyUtil.isEmpty(companys)) {list = companys.stream().map(BeanUtils::companyToDTO).collect(Collectors.toList());}return list;} }

1.4.5.3、DemoEntityServiceImpl.java

@Service @Slf4j public class DemoEntityServiceImpl implements DemoEntityService {@Resourceprivate DemoEntityMapper demoEntityMapper;@Resourceprivate CompanyService companyService;@Resourceprivate UserService userService;@Overridepublic DemoDTO insert(DemoDTO demoDTO) {DemoEntity demoEntity = BeanUtils.dtoToDemo(demoDTO);demoEntity.setStatus(StatusEnum.生效.code);demoEntityMapper.insert(demoEntity);demoDTO.setId(demoEntity.getId());return demoDTO;}@Overridepublic DemoDTO findById(Long id) {DemoEntity demoEntity = demoEntityMapper.selectById(id);return demoEntity == null ? null : BeanUtils.demoToDTO(demoEntity);}@Overridepublic List<DemoDTO> list() {List<DemoDTO> collect = null;List<DemoEntity> list = demoEntityMapper.selectList(null);if (!EmptyUtil.isEmpty(list)) {collect = list.stream().map(BeanUtils::demoToDTO).collect(Collectors.toList());}return collect;}}

1.4.6、Controller

1.4.6.1、UserController.java

@ApiResponses(value = {@ApiResponse(code = 200, message = "訪問正常"),@ApiResponse(code = 301, message = "邏輯錯誤"),@ApiResponse(code = 500, message = "系統(tǒng)錯誤"),@ApiResponse(code = 401, message = "未認(rèn)證"),@ApiResponse(code = 403, message = "禁止訪問"),@ApiResponse(code = 404, message = "url錯誤") }) @Api(description = "demo控制器") @Controller @RequestMapping("hlj/demo") @Slf4j public class UserController {@Autowiredprivate UserService userService;@ApiOperation(value = "insert",notes = "insert",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@PostMapping(value = "insert", produces = "application/json; charset=utf-8")@ResponseBodypublic ResponseBean insert(UserDTO userDTO) {log.info("樣例--------mybaits-plus添加demo實體------數(shù)據(jù)信息{}", userDTO);String validate = ValidateUtils.validate(userDTO, ValidateGroup.HealerJean.class);if (!validate.equals(CommonConstants.COMMON_SUCCESS)) {throw new BusinessException(ResponseEnum.參數(shù)錯誤, validate);}return ResponseBean.buildSuccess(userService.insert(userDTO));}@ApiOperation(notes = "findById",value = "findById",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "demo主鍵", required = true, paramType = "path", dataType = "long"),})@GetMapping("findById/{id}")@ResponseBodypublic ResponseBean findById(@PathVariable Long id) {log.info("樣例--------findById------數(shù)據(jù):id:{}", id);return ResponseBean.buildSuccess(userService.findById(id));}@ApiOperation(notes = "list",value = "list",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("list")@ResponseBodypublic ResponseBean list() {log.info("樣例--------list------");return ResponseBean.buildSuccess(userService.list());}}

1.4.6.2、CompanyController.java

@ApiResponses(value = {@ApiResponse(code = 200, message = "訪問正常"),@ApiResponse(code = 301, message = "邏輯錯誤"),@ApiResponse(code = 500, message = "系統(tǒng)錯誤"),@ApiResponse(code = 401, message = "未認(rèn)證"),@ApiResponse(code = 403, message = "禁止訪問"),@ApiResponse(code = 404, message = "url錯誤") }) @Api(description = "demo控制器") @Controller @RequestMapping("hlj/company") @Slf4j public class CompanyController {@Autowiredprivate CompanyService companyService;@ApiOperation(value = "insert",notes = "insert",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@PostMapping(value = "insert", produces = "application/json; charset=utf-8")@ResponseBodypublic ResponseBean insert(CompanyDTO companyDTO) {log.info("user--------insert------請求參數(shù):{}", companyDTO);return ResponseBean.buildSuccess(companyService.insert(companyDTO));}@ApiOperation(notes = "findById",value = "findById",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "demo主鍵", required = true, paramType = "path", dataType = "long"),})@GetMapping("findById/{id}")@ResponseBodypublic ResponseBean findById(@PathVariable Long id) {log.info("company--------findById------id:{}", id);return ResponseBean.buildSuccess(companyService.findById(id));}@ApiOperation(notes = "list",value = "list",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("list")@ResponseBodypublic ResponseBean list() {log.info("company--------list------");return ResponseBean.buildSuccess(companyService.list());}}

1.4.6.3、DemoController.java

@ApiResponses(value = {@ApiResponse(code = 200, message = "訪問正常"),@ApiResponse(code = 301, message = "邏輯錯誤"),@ApiResponse(code = 500, message = "系統(tǒng)錯誤"),@ApiResponse(code = 401, message = "未認(rèn)證"),@ApiResponse(code = 403, message = "禁止訪問"),@ApiResponse(code = 404, message = "url錯誤") }) @Api(description = "demo控制器") @Controller @RequestMapping("hlj/demo") @Slf4j public class DemoController {@Autowiredprivate DemoEntityService demoEntityService;@ApiOperation(value = "insert",notes = "insert",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@PostMapping(value = "insert", produces = "application/json; charset=utf-8")@ResponseBodypublic ResponseBean insert(DemoDTO demoDTO) {log.info("demo--------insert------請求參數(shù):{}", demoDTO);return ResponseBean.buildSuccess(demoEntityService.insert(demoDTO));}@ApiOperation(notes = "findById",value = "findById",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "demo主鍵", required = true, paramType = "path", dataType = "long"),})@GetMapping("findById/{id}")@ResponseBodypublic ResponseBean findById(@PathVariable Long id) {log.info("demo--------findById------id:{}", id);return ResponseBean.buildSuccess(demoEntityService.findById(id));}@ApiOperation(notes = "list",value = "list",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("list")@ResponseBodypublic ResponseBean list() {log.info("demo--------list------");return ResponseBean.buildSuccess(demoEntityService.list());}}

1.4.6、自定義分表算法 CustomShardingTableAlgorithm

@Slf4j public class CustomShardingTableAlgorithm implements PreciseShardingAlgorithm<Long> {@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {for (String tableName : availableTargetNames) {if (tableName.endsWith(shardingValue.getValue() % 3 + "")) {log.info("表為:{}, 主鍵為:{}, 最終被分到的表為:{}", availableTargetNames, shardingValue, tableName);return tableName;}}throw new IllegalArgumentException();} }

1.4.7、自定義分庫算法:CustomShardingDBAlgorithm

@Slf4j public class CustomShardingDBAlgorithm implements PreciseShardingAlgorithm<Long> {@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {for (String dbName : availableTargetNames) {if (dbName.endsWith(shardingValue.getValue() % 2 + "")) {log.info("庫為:{}, 主鍵為:{}, 最終被分到的庫為:【{}】", availableTargetNames, shardingValue, dbName);return dbName;}}throw new IllegalArgumentException();} }

2、開始測試

基本的增刪改成就不測試了,我們這里主要是測試一些分庫后可能出問題的一些語句

2.1、limit查詢:成功

2.1.1、代碼如下

2.1.1.1、UserService.java

public interface UserService {List<UserDTO> limit(UserDTO userDTO);}

2.1.1.2、UserServiceImpl.java

@Service @Slf4j public class UserServiceImpl implements UserService {/*** limit 成功*/@Overridepublic List<UserDTO> limit(UserDTO userDTO) {Wrapper<User> userWrapper = new QueryWrapper<User>().lambda().orderByDesc(User::getCreateTime).last("limit " + userDTO.getPageNow() + ", " + userDTO.getPageSize());List<User> users = userMapper.selectList(userWrapper);List<UserDTO> list = null;if (!EmptyUtil.isEmpty(users)) {list = users.stream().map(BeanUtils::userToDTO).collect(Collectors.toList());}return list;}}

2.1.1.3、UserController.java

@Controller @RequestMapping("hlj/user") @Slf4j public class UserController {@ApiOperation(notes = "limit",value = "limit",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("limit")@ResponseBodypublic ResponseBean limit(UserDTO userDTO) {log.info("demo--------limit------");return ResponseBean.buildSuccess(userService.limit(userDTO));}}

2.1.2、訪問測試

現(xiàn)在所有的User表數(shù)據(jù)匯總:

namecityagecreateTime
a北京12020-03-30 18:15:14
b北京22020-03-30 18:16:14
c山西32020-03-30 18:16:20
d山西42020-03-30 18:16:27
e河北52020-03-30 18:16:38
f江蘇62020-03-30 18:16:46

2.1.2.1、訪問:pageNow:0,pageSize:2

{"success": true,"result": [{"id": "1244569246752800769","name": "f","city": "江蘇","age": 6,"status": "10","createTime": "2020-03-30 18:16:46","updateTime": "2020-03-30 18:16:46"},{"id": "1244569214813175810","name": "e","city": "河北","age": 5,"status": "10","createTime": "2020-03-30 18:16:38","updateTime": "2020-03-30 18:16:38"}],"msg": "","code": 200,"date": "1585563469572" }

控制臺sql日志

# 日志匯總 Logic SQL: SELECT id,name,city,age,status,create_time,update_time FROM user ORDER BY create_time DESC limit 0, 2 # 數(shù)據(jù)庫日志 Actual SQL: ds0 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_0 ORDER BY create_time DESC limit 0, 2 ShardingSphere-SQL.log[89]Actual SQL: ds0 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_1 ORDER BY create_time DESC limit 0, 2Actual SQL: ds1 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_0 ORDER BY create_time DESC limit 0, 2 Actual SQL: ds1 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_1 ORDER BY create_time DESC limit 0, 2

2.1.2.2、訪問:pageNow:3,pageSize:1

{"success": true,"result": [{"id": "1244569141396078594","name": "c","city": "山西","age": 3,"status": "10","createTime": "2020-03-30 18:16:20","updateTime": "2020-03-30 18:16:20"}],"msg": "","code": 200,"date": "1585563506891" }

控制臺sql日志

# 日志匯總 Actual SQL: SELECT id,name,city,age,status,create_time,update_time FROM user ORDER BY create_time DESC limit 3, 1 # 數(shù)據(jù)庫日志 Actual SQL: ds0 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_0 ORDER BY create_time DESC limit 0, 4Actual SQL: ds0 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_1 ORDER BY create_time DESC limit 0, 4Actual SQL: ds1 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_0 ORDER BY create_time DESC limit 0, 4Actual SQL: ds1 ::: SELECT id,name,city,age,status,create_time,update_time FROM user_1 ORDER BY create_time DESC limit 0, 4

2.1.3、歸納總結(jié):

成功,可以看到分表向每個數(shù)據(jù)庫的每個表中發(fā)送了sql語句

2.2、groupBy + 函數(shù) :成功

2.2.1、代碼如下

2.2.1.1、UserMapper.java

public interface UserMapper extends BaseMapper<User> {List<UserRefCompany> groupByCity(); }

2.2.1.2、UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.healerjean.proj.dao.mapper.UserMapper"><select id="groupByCity" resultType="com.healerjean.proj.pojo.UserRefCompany">select city , sum(age) as sumAge, avg(age) as avgAge from user group by city</select></mapper>

2.2.1.3、UserService.java

@Service @Slf4j public class UserServiceImpl implements UserService {/*** groupBy 成功*/@Overridepublic List<UserRefCompany> group() {List<UserRefCompany> list = userMapper.groupByCity();return list;}}

2.2.1.4、UserController.java

@Controller @RequestMapping("hlj/user") @Slf4j public class UserController {@ApiOperation(notes = "group",value = "group",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("group")@ResponseBodypublic ResponseBean group() {log.info("demo--------group------");return ResponseBean.buildSuccess(userService.group());}}

2.1.2、測試

現(xiàn)在所有的User表數(shù)據(jù)匯總:

namecityage
a北京1
b北京2
c山西3
d山西4
e河北5
f江蘇6

2.1.2.1、訪問測試

{"success": true,"result": [{"userId": null,"name": null,"city": "北京","status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": 1,"sumAge": 3},{"userId": null,"name": null,"city": "山西","status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": 3,"sumAge": 7},{"userId": null,"name": null,"city": "江蘇","status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": 6,"sumAge": 6},{"userId": null,"name": null,"city": "河北","status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": 5,"sumAge": 5}],"msg": "","code": 200,"date": "1585563964870" }

控制臺日志

Logic SQL: select city , sum(age) as sumAge, avg(age) as avgAge from user group by city Actual SQL: ds0 ::: select city , sum(age) as sumAge, avg(age) as avgAge , COUNT(age) AS AVG_DERIVED_COUNT_0 , SUM(age) AS AVG_DERIVED_SUM_0 from user_0 group by city ORDER BY city ASC ShardingSphere-SQL.log[89]Actual SQL: ds0 ::: select city , sum(age) as sumAge, avg(age) as avgAge , COUNT(age) AS AVG_DERIVED_COUNT_0 , SUM(age) AS AVG_DERIVED_SUM_0 from user_1 group by city ORDER BY city ASC Actual SQL: ds1 ::: select city , sum(age) as sumAge, avg(age) as avgAge , COUNT(age) AS AVG_DERIVED_COUNT_0 , SUM(age) AS AVG_DERIVED_SUM_0 from user_0 group by city ORDER BY city ASC Actual SQL: ds1 ::: select city , sum(age) as sumAge, avg(age) as avgAge , COUNT(age) AS AVG_DERIVED_COUNT_0 , SUM(age) AS AVG_DERIVED_SUM_0 from user_1 group by city ORDER BY city ASC

2.1.3、歸納總結(jié):

成功,可以看到分表向每個數(shù)據(jù)庫的每個表中發(fā)送了sql語句 (取出數(shù)據(jù)后,自動講里面獲取的數(shù)字進(jìn)行計算)

2.3、between and :成功

2.3.1、代碼如下

2.3.1.1、UserService.java

public interface UserService {List<UserDTO> between();}

2.3.1.2、UserServiceImpl.java

@Service @Slf4j public class UserServiceImpl implements UserService {/*** between 成功*/@Overridepublic List<UserDTO> between() {Wrapper<User> userWrapper = new QueryWrapper<User>().lambda().between(User::getAge, 1, 3).orderByDesc(User::getCreateTime);List<User> users = userMapper.selectList(userWrapper);List<UserDTO> list = null;if (!EmptyUtil.isEmpty(users)) {list = users.stream().map(BeanUtils::userToDTO).collect(Collectors.toList());}return list;}}

2.3.1.3、UserController.java

@Controller @RequestMapping("hlj/user") @Slf4j public class UserController {@ApiOperation(notes = "between",value = "group",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("between")@ResponseBodypublic ResponseBean between() {log.info("demo--------between------");return ResponseBean.buildSuccess(userService.between());}}

2.3.2、測試

現(xiàn)在所有的User表數(shù)據(jù)匯總:

namecityagecreateTime
a北京12020-03-30 18:15:14
b北京22020-03-30 18:16:14
c山西32020-03-30 18:16:20
d山西42020-03-30 18:16:27
e河北52020-03-30 18:16:38
f江蘇62020-03-30 18:16:46

2.3.2.1、訪問測試 :between 1 and 3 orderby createTime desc

{"success": true,"result": [{"id": "1244569141396078594","name": "c","city": "山西","age": 3,"status": "10","createTime": "2020-03-30 18:16:20","updateTime": "2020-03-30 18:16:20"},{"id": "1244569114653196290","name": "b","city": "北京","age": 2,"status": "10","createTime": "2020-03-30 18:16:14","updateTime": "2020-03-30 18:16:14"},{"id": "1244568862747492353","name": "a","city": "北京","age": 1,"status": "10","createTime": "2020-03-30 18:15:14","updateTime": "2020-03-30 18:15:14"}],"msg": "","code": 200,"date": "1585564394319" }

2.3.3、歸納總結(jié):

成功,可以看到分表向每個數(shù)據(jù)庫的每個表中發(fā)送了sql語句

2.2、left join: 連接查詢

2.2.1、代碼如下

2.2.1.1、UserMapper.java

public interface UserMapper extends BaseMapper<User> {List<UserRefCompany> leftJoin();}

2.2.1.2、UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.healerjean.proj.dao.mapper.UserMapper"><select id="leftJoin" resultType="com.healerjean.proj.pojo.UserRefCompany">select u.id,u.name ,c.id as companyId,c.name as companyName,c.ref_user_id as refUserId,c.company_name_english as companyNameEnglishfrom user u left join company c on u.id = c .ref_user_id order by u.create_time</select></mapper>

2.2.1.3、UserService.java

@Service @Slf4j public class UserServiceImpl implements UserService {/*** left join 設(shè)置了綁定關(guān)系后成功*/@Overridepublic List<UserRefCompany> leftJoin() {List<UserRefCompany> userRefCompanies = userMapper.leftJoin();return userRefCompanies;}}

2.2.1.4、UserController.java

@Controller @RequestMapping("hlj/user") @Slf4j public class UserController {@ApiOperation(notes = "leftJoin",value = "leftJoin",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_JSON_VALUE,response = UserDTO.class)@GetMapping("leftJoin")@ResponseBodypublic ResponseBean leftJoin() {log.info("demo--------leftJoin------");return ResponseBean.buildSuccess( userService.leftJoin());}}

2.2.2、訪問測試:

現(xiàn)在所有的User表數(shù)據(jù)匯總:

idnamecityage
1244568862747492353a北京1
1244569114653196290b北京2
1244569141396078594c山西3
1244569167870525442d山西4
1244569214813175810e河北5
1244569246752800769f江蘇6

現(xiàn)在所有的company表數(shù)據(jù)匯總、添加這個數(shù)據(jù)的時候,其實我們已經(jīng)做了一些小動作了,company表的分庫分表是按照ref_user_id進(jìn)行分庫的(和user表中id的分庫策略一致),這樣就保證了后面綁定關(guān)系之后查詢的成功

idref_user_idnamecompany_name_englishcreate_time
12445756321821818891244568862747492353北京小米有限公司xiaomi2020-03-30 18:42:08
12445756925088563211244569114653196290北京字節(jié)跳動zijie2020-03-30 18:42:22
12445757549159055381244569141396078594山西愛酷科技Iku2020-03-30 18:42:37
12445758171677655061244569214813175810河北騰訊tecent2020-03-30 18:42:52

2.2.2.1、默認(rèn)失敗

{"success": true,"result": [{"userId": null,"name": "a","city": null,"status": null,"companyId": 1244585691742093300,"companyName": "北京小米有限公司","companyNameEnglish": "xiaomi","avgAge": null,"sumAge": null},{"userId": null,"name": "a","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "b","city": null,"status": null,"companyId": 1244585869291176000,"companyName": "北京字節(jié)跳動","companyNameEnglish": "zijie","avgAge": null,"sumAge": null},{"userId": null,"name": "b","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "c","city": null,"status": null,"companyId": 1244585918465196000,"companyName": "山西愛酷科技","companyNameEnglish": "Iku","avgAge": null,"sumAge": null},{"userId": null,"name": "c","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "d","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "d","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "e","city": null,"status": null,"companyId": 1244585970768167000,"companyName": "河北騰訊","companyNameEnglish": "tecent","avgAge": null,"sumAge": null},{"userId": null,"name": "e","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "f","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "f","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null}],"msg": "","code": 200,"date": "1585567537634" } Response Code

控制臺日志(整理了下),可以看到下面的查詢類似于卡迪爾積,每個x和每個y數(shù)組里面的分別join了一次,所以導(dǎo)致了錯誤的出現(xiàn),

要查詢的結(jié)果 Logic SQL: select u.id,u.name ,c.id as companyId,c.name as companyName,c.ref_user_id as refUserId,c.company_name_english as companyNameEnglishfrom user uleft join company c on u.id = c .ref_user_id ShardingSphere-SQL.log[89]分庫查詢 Actual SQL: ds0 ::: select ^^^ from user_1 u left join company_1 c on u.id = c .ref_user_id select ^^^ from user_1 u left join company_0 c on u.id = c .ref_user_id select ^^^ from user_0 u left join company_1 c on u.id = c .ref_user_id select ^^^ from user_0 u left join company_0 c on u.id = c .ref_user_id Actual SQL: ds1 ::: select ^^^ from user_1 u left join company_1 c on u.id = c .ref_user_id select ^^^ from user_1 u left join company_0 c on u.id = c .ref_user_id select ^^^ from user_0 u left join company_1 c on u.id = c .ref_user_id select ^^^ from user_0 u left join company_0 c on u.id = c .ref_user_id

2.2.3、配置user和company的綁定關(guān)系 :成功

如果要保證一對一的表關(guān)系,必須保證2點

1、user和company的表數(shù)量以及所在節(jié)點要完全一模一樣

2、從表的的外鍵規(guī)則和主表的外鍵分庫分表策略要一直

# user company 分表 # user_0,user_1,user_2(自定義分表算法) spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..1} spring.shardingsphere.sharding.tables.user.table-strategy.standard.sharding-column=id spring.shardingsphere.sharding.tables.user.table-strategy.standard.precise-algorithm-class-name=com.healerjean.proj.config.datasource.CustomShardingTableAlgorithm # company_0,company_1 (inline分表策略 表達(dá)式 id%2) spring.shardingsphere.sharding.tables.company.actual-data-nodes=ds$->{0..1}.company_$->{0..1} spring.shardingsphere.sharding.tables.company.database-strategy.inline.sharding-column=ref_user_id spring.shardingsphere.sharding.tables.company.database-strategy.inline.algorithm-expression=ds${ref_user_id.longValue() % 2} spring.shardingsphere.sharding.tables.company.table-strategy.inline.sharding-column=ref_user_id spring.shardingsphere.sharding.tables.company.table-strategy.inline.algorithm-expression=company_${ref_user_id.longValue() % 2}# 綁定表規(guī)則列表 spring.shardingsphere.sharding.binding-tables[0]=user,company

2.2.3.1、訪問測試

{"success": true,"result": [{"userId": null,"name": "a","city": null,"status": null,"companyId": 1244585691742093300,"companyName": "北京小米有限公司","companyNameEnglish": "xiaomi","avgAge": null,"sumAge": null},{"userId": null,"name": "b","city": null,"status": null,"companyId": 1244585869291176000,"companyName": "北京字節(jié)跳動","companyNameEnglish": "zijie","avgAge": null,"sumAge": null},{"userId": null,"name": "c","city": null,"status": null,"companyId": 1244585918465196000,"companyName": "山西愛酷科技","companyNameEnglish": "Iku","avgAge": null,"sumAge": null},{"userId": null,"name": "d","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null},{"userId": null,"name": "e","city": null,"status": null,"companyId": 1244585970768167000,"companyName": "河北騰訊","companyNameEnglish": "tecent","avgAge": null,"sumAge": null},{"userId": null,"name": "f","city": null,"status": null,"companyId": null,"companyName": null,"companyNameEnglish": null,"avgAge": null,"sumAge": null}],"msg": "","code": 200,"date": "1585567592799" }

控制臺日志

要查詢的結(jié)果 Logic SQL: select u.id,u.name ,c.id as companyId,c.name as companyName,c.ref_user_id as refUserId,c.company_name_english as companyNameEnglishfrom user uleft join company c on u.id = c .ref_user_id ShardingSphere-SQL.log[89]分庫查詢 Actual SQL: ds0 ::: select ^^^ from user_1 u left join company_1 c on u.id = c .ref_user_id select ^^^ from user_0 u left join company_0 c on u.id = c .ref_user_id Actual SQL: ds1 ::: select ^^^ from user_1 u left join company_1 c on u.id = c .ref_user_id select ^^^ from user_0 u left join company_0 c on u.id = c .ref_user_id

2.3、默認(rèn)數(shù)據(jù)源,配合數(shù)據(jù)源看

默認(rèn)數(shù)據(jù)源指定(不分庫的表)

默認(rèn)數(shù)據(jù)源指定(不分庫的表) spring.shardingsphere.sharding.default-data-source-name=ds0

2.4、配置廣播表

為了防止跨庫查,可以將那些永遠(yuǎn)不會改變的表。在每個庫中復(fù)制一份。一般適用于配置類的數(shù)據(jù),(如果插入數(shù)據(jù),會向所有的數(shù)據(jù)庫同時進(jìn)行插入)

# 配置廣播表(為了防止跨庫查,可以將那些永遠(yuǎn)不會改變的表。在每個庫中復(fù)制一份。一般適用于配置類的數(shù)據(jù),(如果插入數(shù)據(jù),會向所有的數(shù)據(jù)庫同時進(jìn)行插入) spring.shardingsphere.sharding.broadcast-tables=demo_entity

總結(jié)

以上是生活随笔為你收集整理的分库分表之_分库分表 + 复杂查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。