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

a lot of updates

上级 22518247
...@@ -64,25 +64,25 @@ ...@@ -64,25 +64,25 @@
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> <artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version> <version>2.9.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId> <artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version> <version>2.9.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId> <artifactId>springfox-bean-validators</artifactId>
<version>2.8.0</version> <version>2.9.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.gitee.flying-cattle</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>mybatis-dsc-generator</artifactId> <artifactId>swagger-bootstrap-ui</artifactId>
<version>3.0.7.RELEASE</version> <version>1.9.6</version>
</dependency> </dependency>
<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; package com.matrix.md.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/** /**
* Swagger2Config. * Swagger2Config.
...@@ -14,12 +16,14 @@ import springfox.documentation.spring.web.plugins.Docket; ...@@ -14,12 +16,14 @@ import springfox.documentation.spring.web.plugins.Docket;
* @author Matrix <xhyrzldf@gmail.com> * @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 5:12 下午 * @since 2020/5/13 at 5:12 下午
*/ */
@Configuration
@EnableSwagger2
public class Swagger2Config { public class Swagger2Config {
@Bean @Bean
public Docket createRestApi() { public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select() .select()
.apis(RequestHandlerSelectors.basePackage("com.matrix.md.controller")) .apis(RequestHandlerSelectors.basePackage("com.matrix.md"))
.paths(PathSelectors.any()) .paths(PathSelectors.any())
.build(); .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.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.List;
/** /**
* <p> * PlatformVo.
* 共享平台的用户表
* </p>
* *
* @author matrix * @author Matrix <xhyrzldf@gmail.com>
* @since 2020-05-13 * @since 2020/5/15 at 3:48 下午
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true) @Accessors(chain = true)
@ApiModel(value="Suser对象", description="共享平台的用户表") @EqualsAndHashCode(callSuper = false)
public class Suser implements Serializable { @ApiModel("用于视图层操作的平台对象,用于描述平台的基本信息")
public class PlatformVo {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "姓名") @ApiModelProperty(value = "写入方的平台名", example = "test-writer", position = 0)
private String name; private String name;
@ApiModelProperty(value = "年龄") @ApiModelProperty(value = "要新建的表结构信息", position = 1)
private Integer age; private List<TableVo> tableList;
@ApiModelProperty(value = "邮箱地址")
private String email;
} }
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; package com.matrix.md.sdb.mapper;
import com.matrix.md.sdb.entity.Suser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.matrix.md.sdb.entity.ColumnInfo;
import org.springframework.stereotype.Repository;
/** /**
* <p> * <p>
* 共享平台的用户表 Mapper 接口 * 表里每一列的结构信息 Mapper 接口
* </p> * </p>
* *
* @author matrix * @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; package com.matrix.md.utils;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils;
...@@ -7,12 +8,11 @@ import com.baomidou.mybatisplus.generator.AutoGenerator; ...@@ -7,12 +8,11 @@ import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo; 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.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine; import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Scanner;
/** /**
* mybatis auto code generator * mybatis auto code generator
...@@ -54,6 +54,7 @@ public class CodeGenerator { ...@@ -54,6 +54,7 @@ public class CodeGenerator {
gc.setAuthor("matrix"); gc.setAuthor("matrix");
gc.setOpen(false); gc.setOpen(false);
gc.setSwagger2(true); gc.setSwagger2(true);
gc.setIdType(IdType.ASSIGN_ID);
mpg.setGlobalConfig(gc); mpg.setGlobalConfig(gc);
// 数据源配置 // 数据源配置
...@@ -64,6 +65,12 @@ public class CodeGenerator { ...@@ -64,6 +65,12 @@ public class CodeGenerator {
dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root"); dsc.setUsername("root");
dsc.setPassword("ldf123456"); dsc.setPassword("ldf123456");
dsc.setDbQuery(new MySqlQuery() {
@Override
public String[] fieldCustom() {
return new String[]{"null", "default","key"};
}
});
mpg.setDataSource(dsc); mpg.setDataSource(dsc);
// 包配置 // 包配置
...@@ -76,11 +83,17 @@ public class CodeGenerator { ...@@ -76,11 +83,17 @@ public class CodeGenerator {
InjectionConfig cfg = new InjectionConfig() { InjectionConfig cfg = new InjectionConfig() {
@Override @Override
public void initMap() { 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<>(); List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") { focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override @Override
public String outputFile(TableInfo tableInfo) { public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称 // 自定义输入文件名称
...@@ -99,7 +112,7 @@ public class CodeGenerator { ...@@ -99,7 +112,7 @@ public class CodeGenerator {
strategy.setEntityLombokModel(true); strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true); strategy.setRestControllerStyle(true);
strategy.setInclude(scanner("表名")); strategy.setInclude(scanner("表名"));
strategy.setSuperEntityColumns("id"); // strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true); strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_"); strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy); 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; import org.springframework.web.bind.annotation.RequestMapping;
...@@ -7,15 +7,15 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -7,15 +7,15 @@ import org.springframework.web.bind.annotation.RestController;
/** /**
* <p> * <p>
* 共享平台的用户表 前端控制器 * X前置库的用户表 前端控制器
* </p> * </p>
* *
* @author matrix * @author matrix
* @since 2020-05-13 * @since 2020-05-14
*/ */
@RestController @RestController
@RequestMapping("/sdb/suser") @RequestMapping("/xdb/xuser")
public class SuserController { 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.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
...@@ -9,20 +12,9 @@ import org.springframework.stereotype.Repository; ...@@ -9,20 +12,9 @@ import org.springframework.stereotype.Repository;
* @author Matrix <xhyrzldf@gmail.com> * @author Matrix <xhyrzldf@gmail.com>
* @since 2020/5/13 at 10:55 上午 * @since 2020/5/13 at 10:55 上午
*/ */
@DS("xdb")
@Repository @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: ...@@ -2,6 +2,12 @@ spring:
profiles: profiles:
active: mysql active: mysql
jackson:
#属性为NULL 不序列化
default-property-inclusion: non_null
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
logging: logging:
level: level:
com: com:
......
create table column_info use sdb;
# platform
drop table if exists platform_info;
create table platform_info
( (
id bigint not null comment '主键,雪花算法生成', id bigint not null comment '主键,雪花算法生成',
name varchar(255) not null comment '列名', name varchar(255) not null comment '平台名',
type varchar(50) not null comment '列的数据类型', type tinyint not null comment '平台类型(1为写入方平台,2为读取方平台,3为同时是写入方与读取方平台)',
is_null tinyint not null comment '是否可以为空,0不能为空,1可以为空', primary key (id)
table_info_id bigint not null comment '该列所属的表的主键id,是外键', ) ENGINE = InnoDB
constraint column_info_pk 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) primary key (id)
) ) ENGINE = InnoDB
comment '表里每一列的结构信息'; DEFAULT CHARSET = utf8 comment '数据库信息';
drop table if exists table_info;
# table
create table table_info create table table_info
( (
id bigint not null comment '主键,雪花算法生成', id bigint not null comment '主键,雪花算法生成',
platform_type tinyint not null comment '平台类型(1为写入方平台,2为读取方平台)', name varchar(255) not null comment '表名',
table_name varchar(255) not null comment '表名', build_type tinyint not null default 1 comment '建立类型(0代表由共享平台自行建立,1代表由写入方/读取方发起建立请求)',
constraint table_info_pk database_id bigint not null comment '该表所属的数据库主键id,是逻辑外键',
primary key (id) primary key (id)
) ) ENGINE = InnoDB
comment '每个平台对应的表信息'; 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 '列名',
data_type varchar(50) not null comment '列的数据类型',
is_null tinyint not null comment '是否可以为空,0不能为空,1可以为空',
table_info_id bigint not null comment '该列所属的表的主键id,是逻辑外键',
primary key (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8 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" ?> <?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" > <!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"> <update id="createNewTable">
CREATE TABLE ${tableName} CREATE TABLE ${table.tableName}
( (
id bigint(20) NOT NULL AUTO_INCREMENT, id bigint(20) NOT NULL ,
${propertyName} ${propertyType} 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) PRIMARY KEY (id)
) )
</update> </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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论