提交 dc7570af authored 作者: Matrix's avatar Matrix

a lot of updates

上级 22518247
......@@ -64,25 +64,25 @@
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.8.0</version>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.gitee.flying-cattle</groupId>
<artifactId>mybatis-dsc-generator</artifactId>
<version>3.0.7.RELEASE</version>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
......
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.matrix.md.api;
/**
* <p>
* REST API 响应码
* </p>
*
* @author geekidea
* @since 2018-11-08
*/
public enum ApiCode {
/**
* 操作成功
**/
SUCCESS(200, "操作成功"),
/**
* 非法访问
**/
UNAUTHORIZED(401, "非法访问"),
/**
* 没有权限
**/
NOT_PERMISSION(403, "没有权限"),
/**
* 你请求的资源不存在
**/
NOT_FOUND(404, "你请求的资源不存在"),
/**
* 操作失败
**/
FAIL(500, "操作失败"),
/**
* 登录失败
**/
LOGIN_EXCEPTION(4000, "登录失败"),
/**
* 系统异常
**/
SYSTEM_EXCEPTION(5000, "系统异常"),
/**
* 请求参数校验异常
**/
PARAMETER_EXCEPTION(5001, "请求参数校验异常"),
/**
* 请求参数解析异常
**/
PARAMETER_PARSE_EXCEPTION(5002, "请求参数解析异常"),
/**
* HTTP内容类型异常
**/
HTTP_MEDIA_TYPE_EXCEPTION(5003, "HTTP内容类型异常"),
/**
* 系统处理异常
**/
SPRING_BOOT_PLUS_EXCEPTION(5100, "系统处理异常"),
/**
* 业务处理异常
**/
BUSINESS_EXCEPTION(5101, "业务处理异常"),
/**
* 数据库处理异常
**/
DAO_EXCEPTION(5102, "数据库处理异常"),
/**
* 验证码校验异常
**/
VERIFICATION_CODE_EXCEPTION(5103, "验证码校验异常"),
/**
* 登录授权异常
**/
AUTHENTICATION_EXCEPTION(5104, "登录授权异常"),
/**
* 没有访问权限
**/
UNAUTHENTICATED_EXCEPTION(5105, "没有访问权限"),
/**
* 没有访问权限
**/
UNAUTHORIZED_EXCEPTION(5106, "没有访问权限"),
/**
* JWT Token解析异常
**/
JWTDECODE_EXCEPTION(5107, "Token解析异常"),
HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION(5108, "METHOD NOT SUPPORTED"),
;
private final int code;
private final String message;
ApiCode(final int code, final String message) {
this.code = code;
this.message = message;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.matrix.md.api;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
* REST API 返回结果
* </p>
*
* @author geekidea
* @since 2018-11-08
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
@ApiModel(value = "通用返回体")
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = 8004487252556526569L;
/**
* 响应码
*/
@ApiModelProperty(value = "响应码", example = "200", position = 0)
private int code;
/**
* 是否成功
*/
@ApiModelProperty(value = "响应是否成功", example = "true", position = 1)
private boolean success;
/**
* 响应消息
*/
@ApiModelProperty(value = "响应消息", example = "请求成功", position = 2)
private String message;
/**
* 响应时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "响应时间", example = "2012-02-02 00:01:55", position = 4)
private Date time;
/**
* 响应数据
*/
@ApiModelProperty(value = "响应附带的数据,多为JSON格式", example = "{\"示例数据\":\"会返回一些JSON格式的数据\"}", position = 3)
private T data;
public ApiResult() {
time = new Date();
}
public static ApiResult<Boolean> result(boolean flag) {
if (flag) {
return ok();
}
return fail();
}
public static ApiResult<Boolean> result(ApiCode apiCode) {
return result(apiCode, null);
}
public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
return result(apiCode, null, data);
}
public static <T> ApiResult<T> result(ApiCode apiCode, String message, T data) {
boolean success = false;
if (apiCode.getCode() == ApiCode.SUCCESS.getCode()) {
success = true;
}
String apiMessage = apiCode.getMessage();
if (StringUtils.isBlank(message)) {
message = apiMessage;
}
return (ApiResult<T>) ApiResult.builder()
.code(apiCode.getCode())
.message(message)
.data(data)
.success(success)
.time(new Date())
.build();
}
public static ApiResult<Boolean> ok() {
return ok(null);
}
public static <T> ApiResult<T> ok(T data) {
return result(ApiCode.SUCCESS, data);
}
public static <T> ApiResult<T> ok(T data, String message) {
return result(ApiCode.SUCCESS, message, data);
}
public static ApiResult<Map<String, Object>> okMap(String key, Object value) {
Map<String, Object> map = new HashMap<>(1);
map.put(key, value);
return ok(map);
}
public static ApiResult<Boolean> fail(ApiCode apiCode) {
return result(apiCode, null);
}
public static ApiResult<String> fail(String message) {
return result(ApiCode.FAIL, message, null);
}
public static <T> ApiResult<T> fail(ApiCode apiCode, T data) {
if (ApiCode.SUCCESS == apiCode) {
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
}
return result(apiCode, data);
}
public static ApiResult<String> fail(Integer errorCode, String message) {
return new ApiResult<String>()
.setSuccess(false)
.setCode(errorCode)
.setMessage(message);
}
public static ApiResult<Map<String, Object>> fail(String key, Object value) {
Map<String, Object> map = new HashMap<>(1);
map.put(key, value);
return result(ApiCode.FAIL, map);
}
public static ApiResult<Boolean> fail() {
return fail(ApiCode.FAIL);
}
}
\ No newline at end of file
package com.matrix.md.common;
import io.swagger.annotations.ApiModel;
/**
* DBSource.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/20 at 3:31 下午
*/
@ApiModel(value = "代表三类数据源,用该枚举来确定实际操作数据库是在哪个DB内操作")
public enum DBSource {
/**
* 代表三类数据源,用该枚举来确定实际操作数据库是在哪个DB内操作
*/
SDB,
XDB,
YDB;
}
package com.matrix.md.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2Config.
......@@ -14,12 +16,14 @@ import springfox.documentation.spring.web.plugins.Docket;
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 5:12 下午
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.matrix.md.controller"))
.apis(RequestHandlerSelectors.basePackage("com.matrix.md"))
.paths(PathSelectors.any())
.build();
}
......
package com.matrix.md.core.dao;
import com.matrix.md.sdb.entity.vo.TableVo;
import org.apache.ibatis.annotations.Param;
/**
* OperateTableMapper.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/21 at 11:41 上午
*/
public interface OperateTableMapper {
/**
* create table
*
* @param tableVo {{@link TableVo}}
* @return update lines,under normal circumstances it is actually 0
*/
int createNewTable(@Param("table") TableVo tableVo);
/**
* delete table
*
* @param tableName tableName that u wanna delete
* @return update lines ,under normal circumstances it is actually 0
*/
int dropTable(@Param("tableName") String tableName);
}
package com.matrix.md.sdb.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.matrix.md.api.ApiResult;
import com.matrix.md.sdb.entity.TableInfo;
import com.matrix.md.sdb.entity.param.DelColumnParam;
import com.matrix.md.sdb.entity.vo.DynamicDataVo;
import com.matrix.md.sdb.mapper.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* OperateDataController.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/17 at 11:55 下午
*/
@Slf4j
@RestController
@RequestMapping("/opt/data")
@Api(tags = "用户动态操作数据接口")
public class OperateDataController {
@Autowired
private OperateSdbTableMapper operateSdbTableMapper;
@Autowired
private OperateDataMapper operateDataMapper;
@Autowired
private PlatformInfoMapper platformInfoMapper;
@Autowired
private DatabaseInfoMapper databaseInfoMapper;
@Autowired
private TableInfoMapper tableInfoMapper;
@Autowired
private ColumnInfoMapper columnInfoMapper;
/**
* 验证身份后,提供要操作的表id以及要插入的数据
*
* @return 成功插入数据的行数
*/
@PostMapping
@ApiOperation(value = "动态插入表数据", response = ApiResult.class)
public ApiResult<List<String>> insertData(@RequestBody DynamicDataVo dataVo) {
// TODO: 2020/5/18 这里还需要做参数验证(严格)相关的事情
Long tableId = dataVo.getTableId();
String tableName = tableInfoMapper.selectById(tableId).getName();
List<Map<String, String>> dataMapList = dataVo.getData();
// 考虑到人大进仓数据库无自增,这里手动增加id以及提前生成好分布式id(种子为tableName)
List<String> columnNames = new ArrayList<>(dataMapList.get(0).keySet());
columnNames.add(0, "id");
List<List<String>> columnValues = new ArrayList<>();
//用于返回信息返回已插入数据的id
List<String> addedIdList = new ArrayList<>();
for (Map<String, String> dataMap : dataMapList) {
List<String> singleValueList = new ArrayList<>(dataMap.values());
String nextId = new DefaultIdentifierGenerator().nextId(tableName).toString();
addedIdList.add(nextId);
singleValueList.add(0, nextId);
columnValues.add(singleValueList);
}
int updateCount = operateDataMapper.dynamicInsertBatchData(tableName, columnNames, columnValues);
return ApiResult.ok(addedIdList, String.format("成功插入%d条数据,数据的主键id在data字段里查看", updateCount));
}
@DeleteMapping
@ApiOperation(value = "动态删除表数据", response = ApiResult.class)
public ApiResult<Integer> deleteData(@RequestBody DelColumnParam delColumnParam) {
//实际的逻辑需要补充的除了身份认证以外,还要这张表是不是在用户->库下(对于不同用户/库来讲,表名很明显会发生重复)
int deleteCount = operateDataMapper.dynamicDeleteBatchData(delColumnParam);
return ApiResult.ok(deleteCount, "删除数据成功,删除的数据量请查看data字段的值");
}
@GetMapping
@ApiOperation(value = "动态查询表数据", response = ApiResult.class)
public ApiResult findData(@RequestParam("tableName") @ApiParam(value = "要查询的表名", example = "student") String tableName) {
List<Map<String,Object>> result = operateDataMapper.dynamicSelectData(tableName);
return ApiResult.ok(result);
}
}
package com.matrix.md.sdb.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.matrix.md.api.ApiResult;
import com.matrix.md.common.DBSource;
import com.matrix.md.sdb.entity.TableInfo;
import com.matrix.md.sdb.entity.vo.PlatformVo;
import com.matrix.md.sdb.mapper.ColumnInfoMapper;
import com.matrix.md.sdb.mapper.TableInfoMapper;
import com.matrix.md.sdb.service.IOperateTableService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* OperaTableMapper.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/15 at 2:27 下午
*/
@Slf4j
@RestController
@RequestMapping("/opt/tables")
@Api(tags = "用户动态操作表接口")
public class OperateTableController {
@Resource(name = "IOptTableServiceImpl")
private IOperateTableService operateTableService;
@Autowired
private TableInfoMapper tableInfoMapper;
/**
* <p>1.读取要创建的表结构,并进行表创建</p>
* <p>2.记录已经创建的表结构以及他们的之间的绑定关系</p>
* <p>3.将绑定关系返回</p>
* <p>PS: 操作1与2应当是在同一个事物下</p>
*
* @param platformVo 要创建表的表信息
* @return
*/
@PostMapping
@ApiOperation(value = "动态创建表", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
response = TableInfo.class, responseContainer = "List")
public ApiResult<List<TableInfo>> createTable(@RequestBody PlatformVo platformVo,
@RequestParam(value = "source", required = false) @ApiParam(value = "要操作的数据源(SDB/XDB/YDB)", example = "SDB") DBSource dbSource) {
List<TableInfo> tableInfoResults = operateTableService.dynamicCreateTables(platformVo, dbSource);
return ApiResult.ok(tableInfoResults);
}
/**
* <p>1.删除数据库里的表结构</p>
* <p>1.删除table_info与column中记录的表结构信息</p>
*
* @param tableName
* @return
*/
@DeleteMapping
@ApiOperation(value = "动态删除表", response = ApiResult.class)
public ApiResult<String> dropTable(
@RequestParam("tableName") @ApiParam(value = "要删除的表名", example = "student") String tableName,
@RequestParam(value = "source", required = false) @ApiParam(value = "要操作的数据源(SDB/XDB/YDB)", example = "SDB") DBSource dbSource) {
int delColumnLines = 0;
delColumnLines = operateTableService.dynamicDeleteTables(tableName, dbSource);
return ApiResult.ok(String.format("成功删除了%s表以及其相关的%d列的数据", tableName, delColumnLines));
}
/**
* 查询数据目录,因为是DEMO所以没有设定很严格的一些权限条件之类的
*
* @return
*/
@GetMapping
@ApiOperation(value = "查询数据目录", response = TableInfo.class, responseContainer = "List")
public ApiResult<List<TableInfo>> findTableInfos() {
List<TableInfo> tableInfos = tableInfoMapper.selectList(Wrappers.emptyWrapper());
return ApiResult.ok(tableInfos);
}
}
package com.matrix.md.sdb.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import com.matrix.md.sdb.entity.vo.ColumnVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 表里每一列的结构信息
*
* @author matrix
* @since 2020-05-14
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "ColumnInfo对象")
public class ColumnInfo implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "主键,雪花算法生成不能为空")
@ApiModelProperty("主键,雪花算法生成")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@NotBlank(message = "列名不能为空")
@ApiModelProperty("列名")
private String name;
@NotBlank(message = "列的数据类型不能为空")
@ApiModelProperty("列的数据类型")
private String dataType;
@NotNull(message = "是否可以为空,0不能为空,1可以为空不能为空")
@ApiModelProperty("是否可以为空,0不能为空,1可以为空")
private Integer isNull;
@NotNull(message = "该列所属的表的主键id,是逻辑外键不能为空")
@ApiModelProperty("该列所属的表的主键id,是逻辑外键")
private Long tableInfoId;
}
package com.matrix.md.sdb.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 数据库信息
*
* @author matrix
* @since 2020-05-14
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "DatabaseInfo对象")
@TableName(resultMap = "databaseMap")
public class DatabaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "主键,雪花算法生成不能为空")
@ApiModelProperty("主键,雪花算法生成")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@NotBlank(message = "库名不能为空")
@ApiModelProperty("库名")
private String name;
@NotBlank(message = "库地址不能为空")
@ApiModelProperty("库地址")
private String address;
@NotNull(message = "库类型(1为写入方的前置库,2为读取方的前置库)不能为空")
@ApiModelProperty("库类型(1为写入方的前置库,2为读取方的前置库)")
private Integer dbType;
@NotNull(message = "该库所属的平台主键id,是逻辑外键不能为空")
@ApiModelProperty("该库所属的平台主键id,是逻辑外键")
private Long platformId;
@TableField(exist = false)
private List<TableInfo> tableInfoList = new ArrayList<>();
}
package com.matrix.md.sdb.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 平台信息
*
* @author matrix
* @since 2020-05-14
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "PlatformInfo对象")
@TableName(resultMap = "platformMap")
public class PlatformInfo implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "主键,雪花算法生成不能为空")
@ApiModelProperty("主键,雪花算法生成")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@NotBlank(message = "平台名不能为空")
@ApiModelProperty("平台名")
private String name;
@NotNull(message = "平台类型(1为写入方平台,2为读取方平台,3为同时是写入方与读取方平台)不能为空")
@ApiModelProperty("平台类型(1为写入方平台,2为读取方平台,3为同时是写入方与读取方平台)")
private Integer type;
@TableField(exist = false)
private List<DatabaseInfo> databaseInfoList = new ArrayList<>();
}
package com.matrix.md.sdb.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.matrix.md.sdb.entity.vo.TableVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* 每个平台对应的表信息
*
* @author matrix
* @since 2020-05-14
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "TableInfo对象")
@TableName(resultMap = "tableMap")
public class TableInfo implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "主键,雪花算法生成不能为空")
@ApiModelProperty(value = "主键,雪花算法生成",position = 0)
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@NotBlank(message = "表名不能为空")
@ApiModelProperty(value = "表名",position = 1)
private String name;
@ApiModelProperty(value = "建立类型(0代表由共享平台自行建立,1代表由写入方/读取方发起建立请求)",position = 2)
private Integer buildType;
@NotNull(message = "该表所属的数据库主键id,是逻辑外键不能为空")
@ApiModelProperty(value = "该表所属的数据库主键id,是逻辑外键",position = 3)
private Long databaseId;
@TableField(exist = false)
@ApiModelProperty(position = 4)
private List<ColumnInfo> columnInfos;
}
package com.matrix.md.sdb.entity.dto;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* DynamicColumn.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/18 at 3:19 下午
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "动态列对象")
public class DynamicColumn {
private String columnName;
private String columnValue;
}
package com.matrix.md.sdb.entity.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* DynamicColumnVo.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/18 at 4:36 下午
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel("用于动态删除数据接口的参数对象")
public class DelColumnParam {
@ApiModelProperty(value = "要删除数据所属表的表名", example = "student", position = 0)
private String tableName;
@ApiModelProperty(value = "要删除的数据所属表的主键字段名称", example = "id", position = 1)
private String primaryKeyName;
@ApiModelProperty(value = "要删除的数据主键id", example = "[16,17,18]", position = 2)
private List<Long> columnsIds;
}
package com.matrix.md.sdb.entity.vo;
import com.matrix.md.sdb.entity.ColumnInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* ColumnVo.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/15 at 2:31 下午
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel("用于视图层操作的列对象,里面记录了列结构信息")
public class ColumnVo {
@ApiModelProperty(value = "列名", example = "name")
private String columnName;
@ApiModelProperty(value = "列的数据类型", example = "varchar(255)")
private String columnType;
@ApiModelProperty(value = "该列是否允许为null,0不允许,1允许", example = "0")
private int isNull;
public ColumnInfo tran2Column(){
return new ColumnInfo().setName(columnName)
.setDataType(columnType)
.setIsNull(isNull);
}
}
package com.matrix.md.sdb.entity.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
import java.util.Map;
/**
* DynamicDataVo.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/18 at 12:11 上午
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel("用于视图层操作的列对象,用于描述动态列的数据结构")
public class DynamicDataVo {
@ApiModelProperty(value = "该动态数据所属的表的id", example = "123456")
private Long tableId;
@ApiModelProperty(value = "动态数据内容", example = "[{\"name\":\"jack\",\"age\":22},{\"name\":\"rose\",\"age\":23}]", position = 1)
private List<Map<String, String>> data;
}
package com.matrix.md.sdb.entity;
package com.matrix.md.sdb.entity.vo;
import java.io.Serializable;
import com.matrix.md.sdb.entity.TableInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* <p>
* 共享平台的用户表
* </p>
* PlatformVo.
*
* @author matrix
* @since 2020-05-13
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/15 at 3:48 下午
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="Suser对象", description="共享平台的用户表")
public class Suser implements Serializable {
private static final long serialVersionUID=1L;
@EqualsAndHashCode(callSuper = false)
@ApiModel("用于视图层操作的平台对象,用于描述平台的基本信息")
public class PlatformVo {
@ApiModelProperty(value = "姓名")
@ApiModelProperty(value = "写入方的平台名", example = "test-writer", position = 0)
private String name;
@ApiModelProperty(value = "年龄")
private Integer age;
@ApiModelProperty(value = "邮箱地址")
private String email;
@ApiModelProperty(value = "要新建的表结构信息", position = 1)
private List<TableVo> tableList;
}
package com.matrix.md.sdb.entity.vo;
import com.matrix.md.sdb.entity.TableInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* TableVo.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/15 at 2:29 下午
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel("用于视图层操作的表对象,里面记录了表结构信息")
public class TableVo {
@ApiModelProperty(value = "要新建的表名", example = "student", position = 0)
private String tableName;
@ApiModelProperty(value = "要新建的列信息", position = 1)
private List<ColumnVo> columnVoList;
public TableInfo trans2Table(Integer buildType){
return new TableInfo()
.setName(tableName)
.setBuildType(1);
}
}
package com.matrix.md.sdb.mapper;
import com.matrix.md.sdb.entity.Suser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.matrix.md.sdb.entity.ColumnInfo;
import org.springframework.stereotype.Repository;
/**
* <p>
* 共享平台的用户表 Mapper 接口
* 表里每一列的结构信息 Mapper 接口
* </p>
*
* @author matrix
* @since 2020-05-13
* @since 2020-05-14
*/
public interface SuserMapper extends BaseMapper<Suser> {
@Repository
public interface ColumnInfoMapper extends BaseMapper<ColumnInfo> {
}
package com.matrix.md.sdb.mapper;
import com.matrix.md.sdb.entity.DatabaseInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.matrix.md.sdb.entity.TableInfo;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* <p>
* 数据库信息 Mapper 接口
* </p>
*
* @author matrix
* @since 2020-05-14
*/
@Repository
public interface DatabaseInfoMapper extends BaseMapper<DatabaseInfo> {
List<TableInfo> findTablesByDatabaseId(Long id);
}
package com.matrix.md.sdb.mapper;
import com.matrix.md.sdb.entity.param.DelColumnParam;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* OperateDataMapper.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/18 at 3:14 下午
*/
@Repository
public interface OperateDataMapper {
/**
* 批量动态插入数据
* @param tableName 要动态插入数据的表名
* @param columnNames 要插入的列的名称,要插入多列所以为集合
* @param columnValues 要插入列的具体的数据,可能会涉及到批量插入因此是一个复式集合
* @return 成功插入的数据行数
*/
int dynamicInsertBatchData(@Param("tableName") String tableName,
@Param("columnNames") List<String> columnNames,
@Param("columnValues") List<List<String>> columnValues);
/**
* 批量动态删除数据
* @param delColumnParam 具体查看{@link DelColumnParam}字段解释
* @return 成功删除的数据行数
*/
int dynamicDeleteBatchData(@Param("columnParam") DelColumnParam delColumnParam);
/**
* 动态查询表数据
* @param tableName 要查询数据的表名
* @return 以key,value的形式将结果返回
*/
List<Map<String,Object>> dynamicSelectData(@Param("tableName") String tableName);
}
package com.matrix.md.sdb.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.matrix.md.core.dao.OperateTableMapper;
import com.matrix.md.sdb.entity.vo.TableVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
/**
* OperateTableMapper.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 10:55 上午
*/
@DS("sdb")
@Repository
public interface OperateSdbTableMapper extends OperateTableMapper {
}
package com.matrix.md.sdb.mapper;
import com.matrix.md.sdb.entity.DatabaseInfo;
import com.matrix.md.sdb.entity.PlatformInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* <p>
* 平台信息 Mapper 接口
* </p>
*
* @author matrix
* @since 2020-05-14
*/
@Repository
public interface PlatformInfoMapper extends BaseMapper<PlatformInfo> {
List<DatabaseInfo> findDbByPlatId(Long id);
}
package com.matrix.md.sdb.mapper;
import com.matrix.md.sdb.entity.ColumnInfo;
import com.matrix.md.sdb.entity.TableInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* <p>
* 每个平台对应的表信息 Mapper 接口
* </p>
*
* @author matrix
* @since 2020-05-14
*/
@Repository
public interface TableInfoMapper extends BaseMapper<TableInfo> {
List<ColumnInfo> findColumnByTableId(Long id);
}
package com.matrix.md.sdb.service;
import com.matrix.md.common.DBSource;
import com.matrix.md.sdb.entity.TableInfo;
import com.matrix.md.sdb.entity.vo.PlatformVo;
import java.util.List;
/**
* IOperateTableService.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/20 at 3:29 下午
*/
public interface IOperateTableService {
/**
* 动态创建表
* @param platformVo 必须的参数
* @param dbSource 该操作的数据源
* @return 创表成功后的数据结构列表
*/
List<TableInfo> dynamicCreateTables(PlatformVo platformVo, DBSource dbSource);
/**
* 动态删除表
* @param tableName 要删除的表名
* @param dbSource 要操作的数据源
* @return 删除的表的数量
*/
int dynamicDeleteTables(String tableName, DBSource dbSource);
}
package com.matrix.md.sdb.service;
import com.matrix.md.sdb.entity.Suser;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 共享平台的用户表 服务类
* </p>
*
* @author matrix
* @since 2020-05-13
*/
public interface ISuserService extends IService<Suser> {
}
package com.matrix.md.sdb.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.matrix.md.common.DBSource;
import com.matrix.md.core.dao.OperateTableMapper;
import com.matrix.md.sdb.entity.ColumnInfo;
import com.matrix.md.sdb.entity.DatabaseInfo;
import com.matrix.md.sdb.entity.PlatformInfo;
import com.matrix.md.sdb.entity.TableInfo;
import com.matrix.md.sdb.entity.vo.ColumnVo;
import com.matrix.md.sdb.entity.vo.PlatformVo;
import com.matrix.md.sdb.entity.vo.TableVo;
import com.matrix.md.sdb.mapper.*;
import com.matrix.md.sdb.service.IOperateTableService;
import com.matrix.md.xdb.mapper.OperateXdbTableMapper;
import com.matrix.md.ydb.mapper.OperateYdbTableMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import static java.util.stream.Collectors.toList;
/**
* IOperateTableServiceImpl.
* 相同的代码,操作的的数据源是SDB数据源
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/20 at 3:30 下午
*/
@SuppressWarnings("DuplicatedCode")
@Slf4j
@Service
public class IOptTableServiceImpl implements IOperateTableService {
@Autowired
private OperateSdbTableMapper operateSdbTableMapper;
@Autowired
private OperateXdbTableMapper operateXdbTableMapper;
@Autowired
private OperateYdbTableMapper operateYdbTableMapper;
@Autowired
private PlatformInfoMapper platformInfoMapper;
@Autowired
private DatabaseInfoMapper databaseInfoMapper;
@Autowired
private TableInfoMapper tableInfoMapper;
@Autowired
private ColumnInfoMapper columnInfoMapper;
@Override
public List<TableInfo> dynamicCreateTables(PlatformVo platformVo, DBSource dbSource) {
//1.拆解vo对象,将其转换成各个mapper需要的对象
//根据name查询platform id 以及其DB信息
Long platformId = platformInfoMapper.selectOne(Wrappers.<PlatformInfo>lambdaQuery()
.eq(PlatformInfo::getName, platformVo.getName()))
.getId();
Long databaseId = databaseInfoMapper.selectOne(Wrappers.<DatabaseInfo>lambdaQuery()
.eq(DatabaseInfo::getPlatformId, platformId))
.getId();
//操作根据结构进行操作
List<Long> tableIds = new ArrayList<>();
for (TableVo tableParams : platformVo.getTableList()) {
//创建表
operateBySource(dbSource, tableParams, OperateTableMapper::createNewTable);
log.info("成功创建了新表,表信息为{}", tableParams);
//记录表结构信息
TableInfo tableInfo = tableParams.trans2Table(1)
.setDatabaseId(databaseId);
tableInfoMapper.insert(tableInfo);
tableIds.add(tableInfo.getId());
List<ColumnInfo> columnInfoList = tableParams.getColumnVoList().stream()
.map(ColumnVo::tran2Column)
.map(columnInfo -> columnInfo.setTableInfoId(tableInfo.getId()))
.collect(toList());
//记录列结构信息
columnInfoList.forEach(columnInfoMapper::insert);
}
//查询tableIds的表数据并返回 (手动将tableInfoId设为NULL避免信息冗余,完整应当建立一个DTO/VO对象来操作)
return tableInfoMapper.selectBatchIds(tableIds);
}
@Override
public int dynamicDeleteTables(String tableName, DBSource dbSource) {
//根据表名找到表id
Long tableId = tableInfoMapper.selectOne(Wrappers.<TableInfo>lambdaQuery()
.eq(TableInfo::getName, tableName))
.getId();
//删除列信息与表信息
int delColumnLines = columnInfoMapper.delete(Wrappers.<ColumnInfo>lambdaQuery()
.eq(ColumnInfo::getTableInfoId, tableId));
log.info("成功删除了{}表的结构信息,删除列的数量为{}", tableName, delColumnLines);
int delTableLines = tableInfoMapper.deleteById(tableId);
log.info("成功删除了{}表的结构信息,删除表的数量为{}", tableName, delTableLines);
operateBySource(dbSource, tableName, OperateTableMapper::dropTable);
log.info("成功删除了{}表", tableName);
return delColumnLines;
}
/**
* 根据不同的数据源进行不同的数据库操作
*
* @param dbSource 要操作的数据源
* @param param 参数
* @param optFunctions 要进行的数据库操作
* @param <R> 返回值类型
* @param <V> 参数类型
* @return function操作返回的T类型对象
*/
private <V, R> R operateBySource(DBSource dbSource, V param, BiFunction<OperateTableMapper, V, R> optFunctions) {
switch (dbSource) {
case XDB:
return optFunctions.apply(operateXdbTableMapper, param);
case YDB:
return optFunctions.apply(operateYdbTableMapper, param);
default:
case SDB:
return optFunctions.apply(operateSdbTableMapper, param);
}
}
}
package com.matrix.md.sdb.service.impl;
import com.matrix.md.sdb.entity.Suser;
import com.matrix.md.sdb.mapper.SuserMapper;
import com.matrix.md.sdb.service.ISuserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 共享平台的用户表 服务实现类
* </p>
*
* @author matrix
* @since 2020-05-13
*/
@Service
public class SuserServiceImpl extends ServiceImpl<SuserMapper, Suser> implements ISuserService {
}
package com.matrix.md.tmp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author matrix
* @since 2020-05-12
*/
@Slf4j
@RestController
@RequestMapping("/sdb/user")
public class TmpUserController {
// @Autowired
// private SdbUserMapper userMapper;
// @Autowired
// private OperateTableMapper operateTableMapper;
//
// @GetMapping
// public ResponseEntity findUsers() {
// return ResponseEntity.ok(userMapper.selectList(Wrappers.emptyWrapper()));
// }
//
// @PostMapping
// public ResponseEntity insertUsers(@RequestBody User user) {
// int i = userMapper.insert(user);
// return ResponseEntity.ok(i);
// }
//
// @PostMapping("/table")
// public ResponseEntity createTable() {
// int i = operateTableMapper.createNewTable("dyUser", "name", "varchar(255)");
// log.info("{}", i);
// return ResponseEntity.ok("ok");
// }
//
// @DeleteMapping("/table")
// public ResponseEntity dropTable() {
// String tableName = "dyUser";
// int count = operateTableMapper.dropTable(tableName);
// log.info("成功删除了{}表", tableName);
// return ResponseEntity.ok("ok");
// }
}
package com.matrix.md.utils;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
......@@ -7,12 +8,11 @@ import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.*;
/**
* mybatis auto code generator
......@@ -54,6 +54,7 @@ public class CodeGenerator {
gc.setAuthor("matrix");
gc.setOpen(false);
gc.setSwagger2(true);
gc.setIdType(IdType.ASSIGN_ID);
mpg.setGlobalConfig(gc);
// 数据源配置
......@@ -64,6 +65,12 @@ public class CodeGenerator {
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("ldf123456");
dsc.setDbQuery(new MySqlQuery() {
@Override
public String[] fieldCustom() {
return new String[]{"null", "default","key"};
}
});
mpg.setDataSource(dsc);
// 包配置
......@@ -76,11 +83,17 @@ public class CodeGenerator {
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
Map<String, Object> map = new HashMap<>();
// ApiResult
map.put("apiResultClass", "com.matrix.md.api.ApiResult");
// 代码Validation校验
map.put("paramValidation", true);
this.setMap(map);
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
......@@ -99,7 +112,7 @@ public class CodeGenerator {
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setInclude(scanner("表名"));
strategy.setSuperEntityColumns("id");
// strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
......
package com.matrix.md.utils;
import com.gitee.flying.cattle.mdg.entity.BasisInfo;
import com.gitee.flying.cattle.mdg.util.EntityInfoUtil;
import com.gitee.flying.cattle.mdg.util.Generator;
import com.gitee.flying.cattle.mdg.util.MySqlToJavaUtil;
import java.sql.SQLException;
/**
* SwaggerCodeGenerator.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 3:21 下午
*/
public class SwaggerCodeGenerator {
// 基础信息:项目名、作者、版本
public static final String PROJECT = "sharding-platform-demo";
public static final String AUTHOR = "matrix";
public static final String VERSION = "V1.0";
// 数据库连接信息:连接URL、用户名、秘密、数据库名
public static final String URL = "jdbc:mysql://localhost:3306/sdb?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8&allowPublicKeyRetrieval=true";
public static final String NAME = "root";
public static final String PASS = "ldf123456";
public static final String DATABASE = "sdb";
// 类信息:类名、对象名(一般是【类名】的首字母小些)、类说明、时间
public static final String CLASSNAME = "foreign";
public static final String TABLE = "pm_foreign";
public static final String CLASSCOMMENT = "API应用KEY";
public static final String TIME = "2019年10月16日";
public static final String AGILE = System.currentTimeMillis() + "";
// 路径信息,分开路径方便聚合工程项目,微服务项目
public static final String ENTITY_URL = "com.matrix.md.sdb.entity";
public static final String DAO_URL = "com.matrix.md.sdb.mapper";
public static final String XML_URL = "com.matrix.md.sdb.mapper.xml";
public static final String SERVICE_URL = "com.matrix.md.sdb.service";
public static final String SERVICE_IMPL_URL = "com.matrix.md.sdb.service.impl";
public static final String CONTROLLER_URL = "com.matrix.md.sdb.controller";
//是否是Swagger配置
public static final String IS_SWAGGER = "true";
public static void main(String[] args) {
BasisInfo bi = new BasisInfo(PROJECT, AUTHOR, VERSION, URL, NAME, PASS, DATABASE, TIME, AGILE, ENTITY_URL,
DAO_URL, XML_URL, SERVICE_URL, SERVICE_IMPL_URL, CONTROLLER_URL, IS_SWAGGER);
bi.setTable(TABLE);
bi.setEntityName(MySqlToJavaUtil.getClassName(TABLE));
bi.setObjectName(MySqlToJavaUtil.changeToJavaFiled(TABLE));
bi.setEntityComment(CLASSCOMMENT);
try {
bi = EntityInfoUtil.getInfo(bi);
String projectPath = System.getProperty("user.dir");
// 生成文件存放位置
String fileUrl = "projectPath" + "/src/main/java";
//开始生成文件
String aa1 = Generator.createEntity(fileUrl, bi).toString();
String aa2 = Generator.createDao(fileUrl, bi).toString();
String aa3 = Generator.createDaoImpl(fileUrl, bi).toString();
String aa4 = Generator.createService(fileUrl, bi).toString();
String aa5 = Generator.createServiceImpl(fileUrl, bi).toString();
String aa6 = Generator.createController(fileUrl, bi).toString();
// 是否创建swagger配置文件
String aa7 = Generator.createSwaggerConfig(fileUrl, bi).toString();
System.out.println(aa1);
System.out.println(aa2);
System.out.println(aa3);
System.out.println(aa4);
System.out.println(aa5);
System.out.println(aa6);
System.out.println(aa7);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.matrix.md.sdb.controller;
package com.matrix.md.xdb.controller;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -7,15 +7,15 @@ import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 共享平台的用户表 前端控制器
* X前置库的用户表 前端控制器
* </p>
*
* @author matrix
* @since 2020-05-13
* @since 2020-05-14
*/
@RestController
@RequestMapping("/sdb/suser")
public class SuserController {
@RequestMapping("/xdb/xuser")
public class XuserController {
}
package com.matrix.md.tmp;
package com.matrix.md.xdb.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.matrix.md.core.dao.OperateTableMapper;
import com.matrix.md.sdb.entity.vo.TableVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
......@@ -9,20 +12,9 @@ import org.springframework.stereotype.Repository;
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 10:55 上午
*/
@DS("xdb")
@Repository
public interface OperateTableMapper {
public interface OperateXdbTableMapper extends OperateTableMapper {
/**
* create table
* @param tableName 表名
* @param propertyName 属性名
* @param propertyType 属性类型
* @return
*/
int createNewTable(@Param("tableName") String tableName,
@Param("propertyName") String propertyName,
@Param("propertyType") String propertyType);
int dropTable(@Param("tableName")String tableName);
}
package com.matrix.md.ydb.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.matrix.md.core.dao.OperateTableMapper;
import org.springframework.stereotype.Repository;
/**
* OperateTableMapper.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 10:55 上午
*/
@DS("ydb")
@Repository
public interface OperateYdbTableMapper extends OperateTableMapper {
}
......@@ -2,6 +2,12 @@ spring:
profiles:
active: mysql
jackson:
#属性为NULL 不序列化
default-property-inclusion: non_null
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
logging:
level:
com:
......
use sdb;
# platform
drop table if exists platform_info;
create table platform_info
(
id bigint not null comment '主键,雪花算法生成',
name varchar(255) not null comment '平台名',
type tinyint not null comment '平台类型(1为写入方平台,2为读取方平台,3为同时是写入方与读取方平台)',
primary key (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8 comment '平台信息';
# database
drop table if exists database_info;
create table database_info
(
id bigint not null comment '主键,雪花算法生成',
name varchar(255) not null comment '库名',
address varchar(255) not null comment '库地址',
db_type tinyint not null comment '库类型(1为写入方的前置库,2为读取方的前置库)',
platform_id bigint not null comment '该库所属的平台主键id,是逻辑外键',
primary key (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8 comment '数据库信息';
drop table if exists table_info;
# table
create table table_info
(
id bigint not null comment '主键,雪花算法生成',
name varchar(255) not null comment '表名',
build_type tinyint not null default 1 comment '建立类型(0代表由共享平台自行建立,1代表由写入方/读取方发起建立请求)',
database_id bigint not null comment '该表所属的数据库主键id,是逻辑外键',
primary key (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8 comment '每个平台对应的表信息';
# column
drop table if exists column_info;
create table column_info
(
id bigint not null comment '主键,雪花算法生成',
name varchar(255) not null comment '列名',
type varchar(50) not null comment '列的数据类型',
data_type varchar(50) not null comment '列的数据类型',
is_null tinyint not null comment '是否可以为空,0不能为空,1可以为空',
table_info_id bigint not null comment '该列所属的表的主键id,是外键',
constraint column_info_pk
primary key (id)
)
comment '表里每一列的结构信息';
table_info_id bigint not null comment '该列所属的表的主键id,是逻辑外键',
primary key (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8 comment '表里每一列的结构信息';
create table table_info
(
id bigint not null comment '主键,雪花算法生成',
platform_type tinyint not null comment '平台类型(1为写入方平台,2为读取方平台)',
table_name varchar(255) not null comment '表名',
constraint table_info_pk
primary key (id)
)
comment '每个平台对应的表信息';
<?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.matrix.md.sdb.mapper.ColumnInfoMapper">
</mapper>
<?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.matrix.md.sdb.mapper.DatabaseInfoMapper">
<resultMap id="databaseMap" type="com.matrix.md.sdb.entity.DatabaseInfo">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="address" property="address"/>
<result column="dbType" property="dbType"/>
<result column="platform_id" property="platformId"/>
<collection property="tableInfoList" ofType="com.matrix.md.sdb.entity.TableInfo" column="id" select="findTablesByDatabaseId"/>
</resultMap>
<select id="findTablesByDatabaseId" resultType="com.matrix.md.sdb.entity.TableInfo">
select * from table_info t where t.database_id = #{id};
</select>
</mapper>
<?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.matrix.md.sdb.mapper.OperateDataMapper">
<!-- 某些语句压缩成一行是因为换行会影响最后生成SQL语句的实际情况-->
<update id="dynamicInsertBatchData">
insert into ${tableName}<foreach collection="columnNames" index="index" item="name" open="(" close=")" separator=",">${name}</foreach>values<foreach collection="columnValues" index="index" item="values" separator=","><foreach collection="values" index="index" item="value" open="(" close=")" separator=",">'${value}'</foreach></foreach>
</update>
<delete id="dynamicDeleteBatchData">
delete from ${columnParam.tableName} t where t.${columnParam.primaryKeyName} in<foreach collection="columnParam.columnsIds" index="index" item="id" open="(" close=")" separator=",">${id}</foreach>
</delete>
<select id="dynamicSelectData" resultType="java.util.Map">
select * from ${tableName}
</select>
</mapper>
\ No newline at end of file
<?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.matrix.md.tmp.OperateTableMapper">
<mapper namespace="com.matrix.md.sdb.mapper.OperateSdbTableMapper">
<update id="createNewTable">
CREATE TABLE ${tableName}
CREATE TABLE ${table.tableName}
(
id bigint(20) NOT NULL AUTO_INCREMENT,
${propertyName} ${propertyType} not null,
PRIMARY KEY (id)
id bigint(20) NOT NULL ,
<foreach collection="table.columnVoList" index="index" item="item" separator="," close=",">
${item.columnName} ${item.columnType}
<choose>
<when test="item.isNull == 1"/>
<otherwise>
not null
</otherwise>
</choose>
</foreach>
PRIMARY KEY (id)
)
</update>
......
<?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.matrix.md.sdb.mapper.PlatformInfoMapper">
<resultMap id="platformMap" type="com.matrix.md.sdb.entity.PlatformInfo">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="type" property="type"/>
<collection property="databaseInfoList" ofType="com.matrix.md.sdb.entity.DatabaseInfo" column="id" select="findDbByPlatId"/>
</resultMap>
<select id="findDbByPlatId" resultType="com.matrix.md.sdb.entity.DatabaseInfo">
select * from database_info d where d.platform_id = #{id};
</select>
</mapper>
<?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.matrix.md.sdb.mapper.TableInfoMapper">
<resultMap id="tableMap" type="com.matrix.md.sdb.entity.TableInfo">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="build_type" property="buildType"/>
<result column="database_id" property="databaseId"/>
<collection property="columnInfos" ofType="com.matrix.md.sdb.entity.ColumnInfo" column="id" select="findColumnByTableId"/>
</resultMap>
<!-- <collection property="columnInfos" ofType="com.matrix.md.sdb.entity.ColumnInfo" column="table_info_id">-->
<!-- <id column="id" property="id"/>-->
<!-- <result column="name" property="name"/>-->
<!-- <result column="type" property="type"/>-->
<!-- <result column="is_null" property="isNull"/>-->
<!-- </collection>-->
<select id="findColumnByTableId" resultType="com.matrix.md.sdb.entity.ColumnInfo">
select * from column_info c where c.table_info_id = #{id}
</select>
</mapper>
<?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.matrix.md.xdb.mapper.OperateXdbTableMapper">
<update id="createNewTable">
CREATE TABLE ${table.tableName}
(
id bigint(20) NOT NULL ,
<foreach collection="table.columnVoList" index="index" item="item" separator="," close=",">
${item.columnName} ${item.columnType}
<choose>
<when test="item.isNull == 1"/>
<otherwise>
not null
</otherwise>
</choose>
</foreach>
PRIMARY KEY (id)
)
</update>
<update id="dropTable">
DROP TABLE IF EXISTS ${tableName}
</update>
</mapper>
\ No newline at end of file
<?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.matrix.md.ydb.mapper.OperateYdbTableMapper">
<update id="createNewTable">
CREATE TABLE ${table.tableName}
(
id bigint(20) NOT NULL ,
<foreach collection="table.columnVoList" index="index" item="item" separator="," close=",">
${item.columnName} ${item.columnType}
<choose>
<when test="item.isNull == 1"/>
<otherwise>
not null
</otherwise>
</choose>
</foreach>
PRIMARY KEY (id)
)
</update>
<update id="dropTable">
DROP TABLE IF EXISTS ${tableName}
</update>
</mapper>
\ No newline at end of file
package ${package.Entity};
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end
#if(${swagger2})
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#end
#if(${entityLombokModel})
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
#end
#if(${cfg.paramValidation})
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
#end
/**
* $!{table.comment}
*
* @author ${author}
* @since ${date}
*/
#if(${entityLombokModel})
@Data
@Accessors(chain = true)
#if(${superEntityClass})
@EqualsAndHashCode(callSuper = true)
#else
@EqualsAndHashCode(callSuper = false)
#end
#end
#if(${table.convert})
@TableName("${table.name}")
#end
#if(${swagger2})
@ApiModel(value = "${entity}对象")
#end
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {
#elseif(${activeRecord})
public class ${entity} extends Model<${entity}> {
#else
public class ${entity} implements Serializable {
#end
private static final long serialVersionUID = 1L;
## ---------- BEGIN 字段循环遍历 ----------
#foreach($field in ${table.fields})
## 如果没有默认值,且不为空,则设置非空校验
#if(${cfg.paramValidation} && ${field.customMap.null} == 'NO' && !${field.customMap.default})
#if(${field.keyIdentityFlag})
@NotNull(message = "${field.propertyName}不能为空", groups = {Update.class})
#elseif(${field.propertyType} == 'String')
@NotBlank(message = "${field.comment}不能为空")
#else
@NotNull(message = "${field.comment}不能为空")
#end
#end
#if("$!field.comment" != "")
#if(${swagger2})
@ApiModelProperty("${field.comment}")
#else
/**
* ${field.comment}
*/
#end
#end
#if(${field.keyFlag})
## 主键
#if(${field.keyIdentityFlag})
@TableId(value = "${field.name}", type = IdType.AUTO)
#elseif(!$null.isNull(${idType}) && "$!idType" != "")
## 设置主键注解
@TableId(value = "${field.name}", type = IdType.${idType})
#elseif(${field.convert})
@TableId("${field.name}")
#end
## 普通字段
#elseif(${field.fill})
## ----- 存在字段填充设置 -----
#if(${field.convert})
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
#else
@TableField(fill = FieldFill.${field.fill})
#end
#elseif(${field.convert})
@TableField("${field.name}")
#end
## 乐观锁注解
#if(${versionFieldName}==${field.name})
@Version
#end
## 逻辑删除注解
#if(${logicDeleteFieldName}==${field.name})
@TableLogic
#end
private ${field.propertyType} ${field.propertyName};
#end
}
package com.matrix.md;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.matrix.md.sdb.entity.ColumnInfo;
import com.matrix.md.sdb.entity.DatabaseInfo;
import com.matrix.md.sdb.entity.PlatformInfo;
import com.matrix.md.sdb.entity.TableInfo;
import com.matrix.md.sdb.mapper.ColumnInfoMapper;
import com.matrix.md.sdb.mapper.DatabaseInfoMapper;
import com.matrix.md.sdb.mapper.PlatformInfoMapper;
import com.matrix.md.sdb.mapper.TableInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.junit.Assert.*;
/**
* com.matrix.md.BenchmarkTest.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/14 at 4:36 下午
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class BenchmarkTest {
@Autowired
private PlatformInfoMapper platformInfoMapper;
@Autowired
private DatabaseInfoMapper databaseInfoMapper;
@Autowired
private TableInfoMapper tableInfoMapper;
@Autowired
private ColumnInfoMapper columnInfoMapper;
@Test
public void initPlatAndDb(){
//insert platform
platformInfoMapper.delete(Wrappers.emptyWrapper());
PlatformInfo platform = new PlatformInfo().setName("test-writer")
.setType(1);
platformInfoMapper.insert(platform);
Long nextPlatformId = platform.getId();
log.info("nextPlatformId : {}", nextPlatformId);
//insert database
DatabaseInfo database = new DatabaseInfo().setName("User")
.setDbType(1)
.setAddress("localhost:mysql:3306")
.setPlatformId(nextPlatformId);
databaseInfoMapper.insert(database);
}
@Test
public void insertInitData() {
//insert platform
platformInfoMapper.delete(Wrappers.emptyWrapper());
PlatformInfo platform = new PlatformInfo().setName("test-writer")
.setType(1);
platformInfoMapper.insert(platform);
Long nextPlatformId = platform.getId();
log.info("nextPlatformId : {}", nextPlatformId);
//insert database
DatabaseInfo database = new DatabaseInfo().setName("User")
.setDbType(1)
.setAddress("localhost:mysql:3306")
.setPlatformId(nextPlatformId);
databaseInfoMapper.insert(database);
Long nextDatabaseId = database.getId();
log.info("nextDatabaseId : {}", nextDatabaseId);
// insert table
TableInfo table = new TableInfo().setId(null)
.setBuildType(1)
.setDatabaseId(nextDatabaseId)
.setName("test")
.setColumnInfos(Lists.emptyList());
tableInfoMapper.insert(table);
Long nextTableId = table.getId();
log.info("nextTableId : {}", nextTableId);
// insert columns
ColumnInfo column1 = new ColumnInfo().setId(null)
.setIsNull(0)
.setName("user_name")
.setDataType("varchar(255)")
.setTableInfoId(nextTableId);
ColumnInfo column2 = new ColumnInfo().setId(null)
.setIsNull(0)
.setName("user_age")
.setDataType("int")
.setTableInfoId(nextTableId);
columnInfoMapper.insert(column1);
columnInfoMapper.insert(column2);
//check platform not null
PlatformInfo resultPlatform = platformInfoMapper.selectOne(Wrappers.emptyWrapper());
assertNotNull(resultPlatform);
//check database
List<DatabaseInfo> resultDatabaseInfoList = resultPlatform.getDatabaseInfoList();
assertTrue(resultDatabaseInfoList.size() >= 1);
//check table
TableInfo tableResult = tableInfoMapper.selectOne(Wrappers.emptyWrapper());
assertNotNull(tableResult);
// check columnList size large than 1
List<ColumnInfo> columnResults = tableResult.getColumnInfos();
assertTrue(columnResults.size() > 1);
//check if nextTableId successfully cascade
columnResults.forEach(column ->
assertEquals(nextTableId, column.getTableInfoId()));
}
@Test
public void deleteAllData(){
platformInfoMapper.delete(Wrappers.emptyWrapper());
databaseInfoMapper.delete(Wrappers.emptyWrapper());
tableInfoMapper.delete(Wrappers.emptyWrapper());
columnInfoMapper.delete(Wrappers.emptyWrapper());
}
private void printLog(Object context) {
log.info(context.toString());
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论