mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-09-10 23:21:58 +08:00
Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/1.8.0-uniapp
Conflicts: sql/ruoyi-vue-pro.sql yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm
This commit is contained in:
@@ -47,6 +47,10 @@
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
@@ -79,6 +83,11 @@
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>com.github.ulisesbocchio</groupId>
|
||||
<artifactId>jasypt-spring-boot-starter</artifactId> <!-- 加解密 -->
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
|
@@ -4,19 +4,18 @@ import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenDetailRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.CodegenService;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
@@ -33,7 +32,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
@@ -50,19 +48,16 @@ public class CodegenController {
|
||||
@GetMapping("/db/table/list")
|
||||
@ApiOperation(value = "获得数据库自带的表定义列表", notes = "会过滤掉已经导入 Codegen 的表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "tableName", value = "表名,模糊匹配", required = true, example = "yudao", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "tableComment", value = "描述,模糊匹配", required = true, example = "芋道", dataTypeClass = String.class)
|
||||
@ApiImplicitParam(name = "dataSourceConfigId", value = "数据源配置的编号", required = true, example = "1", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "name", value = "表名,模糊匹配", example = "yudao", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "comment", value = "描述,模糊匹配", example = "芋道", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:query')")
|
||||
public CommonResult<List<SchemaTableRespVO>> getSchemaTableList(
|
||||
@RequestParam(value = "tableName", required = false) String tableName,
|
||||
@RequestParam(value = "tableComment", required = false) String tableComment) {
|
||||
// 获得数据库自带的表定义列表
|
||||
List<SchemaTableDO> schemaTables = codegenService.getSchemaTableList(tableName, tableComment);
|
||||
// 移除在 Codegen 中,已经存在的
|
||||
Set<String> existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName);
|
||||
schemaTables.removeIf(table -> existsTables.contains(table.getTableName()));
|
||||
return success(CodegenConvert.INSTANCE.convertList04(schemaTables));
|
||||
public CommonResult<List<DatabaseTableRespVO>> getDatabaseTableList(
|
||||
@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId,
|
||||
@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "comment", required = false) String comment) {
|
||||
return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment));
|
||||
}
|
||||
|
||||
@GetMapping("/table/page")
|
||||
@@ -85,19 +80,10 @@ public class CodegenController {
|
||||
}
|
||||
|
||||
@ApiOperation("基于数据库的表结构,创建代码生成器的表和字段定义")
|
||||
@ApiImplicitParam(name = "tableNames", value = "表名数组", required = true, example = "sys_user", dataTypeClass = List.class)
|
||||
@PostMapping("/create-list-from-db")
|
||||
@PostMapping("/create-list")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
|
||||
public CommonResult<List<Long>> createCodegenListFromDB(@RequestParam("tableNames") List<String> tableNames) {
|
||||
return success(codegenService.createCodegenListFromDB(getLoginUserId(), tableNames));
|
||||
}
|
||||
|
||||
@ApiOperation("基于 SQL 建表语句,创建代码生成器的表和字段定义")
|
||||
@ApiImplicitParam(name = "sql", value = "SQL 建表语句", required = true, example = "sql", dataTypeClass = String.class)
|
||||
@PostMapping("/create-list-from-sql")
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:create')")
|
||||
public CommonResult<Long> createCodegenListFromSQL(@RequestParam("sql") String sql) {
|
||||
return success(codegenService.createCodegenListFromSQL(getLoginUserId(), sql));
|
||||
public CommonResult<List<Long>> createCodegenList(@Valid @RequestBody CodegenCreateListReqVO reqVO) {
|
||||
return success(codegenService.createCodegenList(getLoginUserId(), reqVO));
|
||||
}
|
||||
|
||||
@ApiOperation("更新数据库的表和字段定义")
|
||||
@@ -117,19 +103,6 @@ public class CodegenController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ApiOperation("基于 SQL 建表语句,同步数据库的表和字段定义")
|
||||
@PutMapping("/sync-from-sql")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class),
|
||||
@ApiImplicitParam(name = "sql", value = "SQL 建表语句", required = true, example = "sql", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
|
||||
public CommonResult<Boolean> syncCodegenFromSQL(@RequestParam("tableId") Long tableId,
|
||||
@RequestParam("sql") String sql) {
|
||||
codegenService.syncCodegenFromSQL(tableId, sql);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ApiOperation("删除数据库的表和字段定义")
|
||||
@DeleteMapping("/delete")
|
||||
@ApiImplicitParam(name = "tableId", value = "表编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
|
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("管理后台 - 基于数据库的表结构,创建代码生成器的表和字段定义 Request VO")
|
||||
@Data
|
||||
public class CodegenCreateListReqVO {
|
||||
|
||||
@ApiModelProperty(value = "数据源配置的编号", required = true, example = "1")
|
||||
@NotNull(message = "数据源配置的编号不能为空")
|
||||
private Long dataSourceConfigId;
|
||||
|
||||
@ApiModelProperty(value = "表名数组", required = true, example = "[1, 2, 3]")
|
||||
@NotNull(message = "表名数组不能为空")
|
||||
private List<String> tableNames;
|
||||
|
||||
}
|
@@ -22,7 +22,7 @@ public class CodegenColumnBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "字段类型", required = true, example = "int(11)")
|
||||
@NotNull(message = "字段类型不能为空")
|
||||
private String columnType;
|
||||
private String dataType;
|
||||
|
||||
@ApiModelProperty(value = "字段描述", required = true, example = "年龄")
|
||||
@NotNull(message = "字段描述不能为空")
|
||||
|
@@ -12,10 +12,6 @@ import javax.validation.constraints.NotNull;
|
||||
@Data
|
||||
public class CodegenTableBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "导入类型", required = true, example = "1", notes = "参见 CodegenImportTypeEnum 枚举")
|
||||
@NotNull(message = "导入类型不能为空")
|
||||
private Integer importType;
|
||||
|
||||
@ApiModelProperty(value = "生成场景", required = true, example = "1", notes = "参见 CodegenSceneEnum 枚举")
|
||||
@NotNull(message = "导入类型不能为空")
|
||||
private Integer scene;
|
||||
|
@@ -17,6 +17,9 @@ public class CodegenTableRespVO extends CodegenTableBaseVO {
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "主键编号", required = true, example = "1024")
|
||||
private Integer dataSourceConfigId;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
|
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("管理后台 - 数据库的表定义 Response VO")
|
||||
@Data
|
||||
public class DatabaseTableRespVO {
|
||||
|
||||
@ApiModelProperty(value = "表名称", required = true, example = "yuanma")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "表描述", required = true, example = "芋道源码")
|
||||
private String comment;
|
||||
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("管理后台 - 数据字典的表定义 Response VO")
|
||||
@Data
|
||||
public class SchemaTableRespVO {
|
||||
|
||||
@ApiModelProperty(value = "数据库", required = true, example = "yudao")
|
||||
private String tableSchema;
|
||||
|
||||
@ApiModelProperty(value = "表名称", required = true, example = "yuanma")
|
||||
private String tableName;
|
||||
|
||||
@ApiModelProperty(value = "表描述", required = true, example = "芋道源码")
|
||||
private String tableComment;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
@@ -68,15 +68,15 @@ public class ConfigController {
|
||||
}
|
||||
|
||||
@GetMapping(value = "/get-value-by-key")
|
||||
@ApiOperation(value = "根据参数键名查询参数值", notes = "敏感配置,不允许返回给前端")
|
||||
@ApiOperation(value = "根据参数键名查询参数值", notes = "不可见的配置,不允许返回给前端")
|
||||
@ApiImplicitParam(name = "key", value = "参数键", required = true, example = "yunai.biz.username", dataTypeClass = String.class)
|
||||
public CommonResult<String> getConfigKey(@RequestParam("key") String key) {
|
||||
ConfigDO config = configService.getConfigByKey(key);
|
||||
if (config == null) {
|
||||
return null;
|
||||
}
|
||||
if (config.getSensitive()) {
|
||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_SENSITIVE);
|
||||
if (config.getVisible()) {
|
||||
throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_VISIBLE);
|
||||
}
|
||||
return success(config.getValue());
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ public class ConfigBaseVO {
|
||||
@ApiModelProperty(value = "参数分组", required = true, example = "biz")
|
||||
@NotEmpty(message = "参数分组不能为空")
|
||||
@Size(max = 50, message = "参数名称不能超过50个字符")
|
||||
private String group;
|
||||
private String category;
|
||||
|
||||
@ApiModelProperty(value = "参数名称", required = true, example = "数据库名")
|
||||
@NotBlank(message = "参数名称不能为空")
|
||||
@@ -32,7 +32,7 @@ public class ConfigBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "是否敏感", required = true, example = "true")
|
||||
@NotNull(message = "是否敏感不能为空")
|
||||
private Boolean sensitive;
|
||||
private Boolean visible;
|
||||
|
||||
@ApiModelProperty(value = "备注", example = "备注一下很帅气!")
|
||||
private String remark;
|
||||
|
@@ -18,7 +18,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
||||
@ToString(callSuper = true)
|
||||
public class ConfigPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "参数名称", example = "模糊匹配")
|
||||
@ApiModelProperty(value = "数据源名称", example = "模糊匹配")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "参数键名", example = "yunai.db.username", notes = "模糊匹配")
|
||||
|
@@ -0,0 +1,73 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 数据源配置")
|
||||
@RestController
|
||||
@RequestMapping("/infra/data-source-config")
|
||||
@Validated
|
||||
public class DataSourceConfigController {
|
||||
|
||||
@Resource
|
||||
private DataSourceConfigService dataSourceConfigService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建数据源配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:create')")
|
||||
public CommonResult<Long> createDataSourceConfig(@Valid @RequestBody DataSourceConfigCreateReqVO createReqVO) {
|
||||
return success(dataSourceConfigService.createDataSourceConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新数据源配置")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:update')")
|
||||
public CommonResult<Boolean> updateDataSourceConfig(@Valid @RequestBody DataSourceConfigUpdateReqVO updateReqVO) {
|
||||
dataSourceConfigService.updateDataSourceConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除数据源配置")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')")
|
||||
public CommonResult<Boolean> deleteDataSourceConfig(@RequestParam("id") Long id) {
|
||||
dataSourceConfigService.deleteDataSourceConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得数据源配置")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:query')")
|
||||
public CommonResult<DataSourceConfigRespVO> getDataSourceConfig(@RequestParam("id") Long id) {
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id);
|
||||
return success(DataSourceConfigConvert.INSTANCE.convert(dataSourceConfig));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得数据源配置列表")
|
||||
@PreAuthorize("@ss.hasPermission('infra:data-source-config:query')")
|
||||
public CommonResult<List<DataSourceConfigRespVO>> getDataSourceConfigList() {
|
||||
List<DataSourceConfigDO> list = dataSourceConfigService.getDataSourceConfigList();
|
||||
return success(DataSourceConfigConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.doc;
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
@@ -30,7 +30,7 @@ import java.util.Arrays;
|
||||
@Api(tags = "管理后台 - 数据库文档")
|
||||
@RestController
|
||||
@RequestMapping("/infra/db-doc")
|
||||
public class DbDocController {
|
||||
public class DatabaseDocController {
|
||||
|
||||
@Resource
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
@@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.annotations.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* 数据源配置 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class DataSourceConfigBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "数据源名称", required = true, example = "test")
|
||||
@NotNull(message = "数据源名称不能为空")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro")
|
||||
@NotNull(message = "数据源连接不能为空")
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty(value = "用户名", required = true, example = "root")
|
||||
@NotNull(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.annotations.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@ApiModel("管理后台 - 数据源配置创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DataSourceConfigCreateReqVO extends DataSourceConfigBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "密码", required = true, example = "123456")
|
||||
@NotNull(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
@ApiModel("管理后台 - 数据源配置 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DataSourceConfigRespVO extends DataSourceConfigBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "主键编号", required = true, example = "1024")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.infra.controller.admin.db.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.annotations.*;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@ApiModel("管理后台 - 数据源配置更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DataSourceConfigUpdateReqVO extends DataSourceConfigBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "主键编号", required = true, example = "1024")
|
||||
@NotNull(message = "主键编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "密码", required = true, example = "123456")
|
||||
@NotNull(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
}
|
@@ -6,12 +6,14 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenPreviewR
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableField;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
@@ -23,13 +25,27 @@ public interface CodegenConvert {
|
||||
|
||||
CodegenConvert INSTANCE = Mappers.getMapper(CodegenConvert.class);
|
||||
|
||||
// ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ==========
|
||||
// ========== TableInfo 相关 ==========
|
||||
|
||||
CodegenTableDO convert(SchemaTableDO bean);
|
||||
@Mappings({
|
||||
@Mapping(source = "name", target = "tableName"),
|
||||
@Mapping(source = "comment", target = "tableComment"),
|
||||
})
|
||||
CodegenTableDO convert(TableInfo bean);
|
||||
|
||||
List<CodegenColumnDO> convertList(List<SchemaColumnDO> list);
|
||||
List<CodegenColumnDO> convertList(List<TableField> list);
|
||||
|
||||
CodegenTableRespVO convert(SchemaColumnDO bean);
|
||||
@Mappings({
|
||||
@Mapping(source = "name", target = "columnName"),
|
||||
@Mapping(source = "type", target = "dataType"),
|
||||
@Mapping(source = "comment", target = "columnComment"),
|
||||
@Mapping(source = "metaInfo.nullable", target = "nullable"),
|
||||
@Mapping(source = "keyFlag", target = "primaryKey"),
|
||||
@Mapping(source = "keyIdentityFlag", target = "autoIncrement"),
|
||||
@Mapping(source = "columnType.type", target = "javaType"),
|
||||
@Mapping(source = "propertyName", target = "javaField"),
|
||||
})
|
||||
CodegenColumnDO convert(TableField bean);
|
||||
|
||||
// ========== CodegenTableDO 相关 ==========
|
||||
|
||||
@@ -47,7 +63,7 @@ public interface CodegenConvert {
|
||||
|
||||
List<CodegenColumnDO> convertList03(List<CodegenUpdateReqVO.Column> columns);
|
||||
|
||||
List<SchemaTableRespVO> convertList04(List<SchemaTableDO> list);
|
||||
List<DatabaseTableRespVO> convertList04(List<TableInfo> list);
|
||||
|
||||
// ========== 其它 ==========
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
@@ -18,12 +19,15 @@ public interface ConfigConvert {
|
||||
|
||||
PageResult<ConfigRespVO> convertPage(PageResult<ConfigDO> page);
|
||||
|
||||
@Mapping(source = "configKey", target = "key")
|
||||
ConfigRespVO convert(ConfigDO bean);
|
||||
|
||||
@Mapping(source = "key", target = "configKey")
|
||||
ConfigDO convert(ConfigCreateReqVO bean);
|
||||
|
||||
ConfigDO convert(ConfigUpdateReqVO bean);
|
||||
|
||||
@Mapping(source = "configKey", target = "key")
|
||||
List<ConfigExcelVO> convertList(List<ConfigDO> list);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.infra.convert.db;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
|
||||
/**
|
||||
* 数据源配置 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface DataSourceConfigConvert {
|
||||
|
||||
DataSourceConfigConvert INSTANCE = Mappers.getMapper(DataSourceConfigConvert.class);
|
||||
|
||||
DataSourceConfigDO convert(DataSourceConfigCreateReqVO bean);
|
||||
|
||||
DataSourceConfigDO convert(DataSourceConfigUpdateReqVO bean);
|
||||
|
||||
DataSourceConfigRespVO convert(DataSourceConfigDO bean);
|
||||
|
||||
List<DataSourceConfigRespVO> convertList(List<DataSourceConfigDO> list);
|
||||
|
||||
}
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -15,6 +16,7 @@ import lombok.experimental.Accessors;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "infra_codegen_column", autoResultMap = true)
|
||||
@KeySequence("infra_codegen_column_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@@ -41,7 +43,7 @@ public class CodegenColumnDO extends BaseDO {
|
||||
/**
|
||||
* 字段类型
|
||||
*/
|
||||
private String columnType;
|
||||
private String dataType;
|
||||
/**
|
||||
* 字段描述
|
||||
*/
|
||||
@@ -74,7 +76,6 @@ public class CodegenColumnDO extends BaseDO {
|
||||
/**
|
||||
* Java 属性名
|
||||
*/
|
||||
// @NotBlank(message = "Java属性不能为空")
|
||||
private String javaField;
|
||||
/**
|
||||
* 字典类型
|
||||
|
@@ -1,8 +1,10 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -14,6 +16,7 @@ import lombok.experimental.Accessors;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "infra_codegen_table", autoResultMap = true)
|
||||
@KeySequence("infra_codegen_table_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@@ -25,11 +28,11 @@ public class CodegenTableDO extends BaseDO {
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 导入类型
|
||||
* 数据源编号
|
||||
*
|
||||
* 枚举 {@link CodegenTemplateTypeEnum}
|
||||
* 关联 {@link DataSourceConfigDO#getId()}
|
||||
*/
|
||||
private Integer importType;
|
||||
private Long dataSourceConfigId;
|
||||
/**
|
||||
* 生成场景
|
||||
*
|
||||
|
@@ -1,54 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* MySQL 数据库中的 column 字段定义
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "information_schema.columns", autoResultMap = true)
|
||||
@Data
|
||||
@Builder
|
||||
public class SchemaColumnDO {
|
||||
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
private String tableName;
|
||||
/**
|
||||
* 字段名
|
||||
*/
|
||||
private String columnName;
|
||||
/**
|
||||
* 字段类型
|
||||
*/
|
||||
private String columnType;
|
||||
/**
|
||||
* 字段描述
|
||||
*/
|
||||
private String columnComment;
|
||||
/**
|
||||
* 是否允许为空
|
||||
*/
|
||||
@TableField("case when is_nullable = 'yes' then '1' else '0' end")
|
||||
private Boolean nullable;
|
||||
/**
|
||||
* 是否主键
|
||||
*/
|
||||
@TableField("case when column_key = 'PRI' then '1' else '0' end")
|
||||
private Boolean primaryKey;
|
||||
/**
|
||||
* 是否自增
|
||||
*/
|
||||
@TableField("case when extra = 'auto_increment' then '1' else '0' end")
|
||||
private Boolean autoIncrement;
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
private Integer ordinalPosition;
|
||||
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* MySQL 数据库中的 table 表定义
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "information_schema.tables", autoResultMap = true)
|
||||
@Data
|
||||
@Builder
|
||||
public class SchemaTableDO {
|
||||
|
||||
/**
|
||||
* 数据库
|
||||
*/
|
||||
private String tableSchema;
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
private String tableName;
|
||||
/**
|
||||
* 表描述
|
||||
*/
|
||||
private String tableComment;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.config.ConfigTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
@@ -15,6 +15,7 @@ import lombok.ToString;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_config")
|
||||
@KeySequence("infra_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@@ -26,19 +27,19 @@ public class ConfigDO extends BaseDO {
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 参数分组
|
||||
* 参数分类
|
||||
*/
|
||||
@TableField("`group`")
|
||||
private String group;
|
||||
private String category;
|
||||
/**
|
||||
* 参数名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 参数键名
|
||||
*
|
||||
* 支持多 DB 类型时,无法直接使用 key + @TableField("config_key") 来实现转换,原因是 "config_key" AS key 而存在报错
|
||||
*/
|
||||
@TableField("`key`")
|
||||
private String key;
|
||||
private String configKey;
|
||||
/**
|
||||
* 参数键值
|
||||
*/
|
||||
@@ -48,15 +49,13 @@ public class ConfigDO extends BaseDO {
|
||||
*
|
||||
* 枚举 {@link ConfigTypeEnum}
|
||||
*/
|
||||
@TableField("`type`")
|
||||
private Integer type;
|
||||
/**
|
||||
* 是否敏感
|
||||
* 是否可见
|
||||
*
|
||||
* 对于敏感配置,需要管理权限才能查看
|
||||
* 不可见的参数,一般是敏感参数,前端不可获取
|
||||
*/
|
||||
@TableField("`sensitive`")
|
||||
private Boolean sensitive;
|
||||
private Boolean visible;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_data_source_config")
|
||||
@KeySequence("infra_data_source_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
public class DataSourceConfigDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键编号 - Master 数据源
|
||||
*/
|
||||
public static final Long ID_MASTER = 0L;
|
||||
|
||||
/**
|
||||
* 主键编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 连接名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 数据源连接
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
}
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.file;
|
||||
import cn.iocoder.yudao.framework.file.core.client.FileClientConfig;
|
||||
import cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
@@ -13,8 +14,9 @@ import lombok.*;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "infra_file_config", autoResultMap = true)
|
||||
@KeySequence("infra_file_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
|
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -13,8 +14,9 @@ import lombok.*;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName("infra_file_content")
|
||||
@KeySequence("infra_file_content_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
@@ -13,8 +13,9 @@ import java.io.InputStream;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName("infra_file")
|
||||
@KeySequence("infra_file_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@@ -45,7 +46,6 @@ public class FileDO extends BaseDO {
|
||||
*
|
||||
* 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
|
||||
*/
|
||||
@TableField(value = "`type`")
|
||||
private String type;
|
||||
/**
|
||||
* 文件大小
|
||||
|
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.job;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -12,6 +13,7 @@ import lombok.*;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_job")
|
||||
@KeySequence("infra_job_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.job;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.yudao.module.infra.enums.job.JobLogStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
@@ -14,6 +15,7 @@ import java.util.Date;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_job_log")
|
||||
@KeySequence("infra_job_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.logger;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -15,6 +16,7 @@ import java.util.Date;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_api_access_log")
|
||||
@KeySequence(value = "infra_api_access_log_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.logger;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -21,6 +22,7 @@ import java.util.Date;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@KeySequence(value = "infra_api_error_log_seq")
|
||||
public class ApiErrorLogDO extends BaseDO {
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.dataobject.test;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@@ -11,6 +12,7 @@ import lombok.*;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("infra_test_demo")
|
||||
@KeySequence("infra_test_demo_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
@@ -11,12 +11,14 @@ import java.util.List;
|
||||
public interface CodegenColumnMapper extends BaseMapperX<CodegenColumnDO> {
|
||||
|
||||
default List<CodegenColumnDO> selectListByTableId(Long tableId) {
|
||||
return selectList(new QueryWrapper<CodegenColumnDO>().eq("table_id", tableId)
|
||||
.orderByAsc("ordinal_position"));
|
||||
return selectList(new LambdaQueryWrapperX<CodegenColumnDO>()
|
||||
.eq(CodegenColumnDO::getTableId, tableId)
|
||||
.orderByAsc(CodegenColumnDO::getId));
|
||||
}
|
||||
|
||||
default void deleteListByTableId(Long tableId) {
|
||||
delete(new QueryWrapper<CodegenColumnDO>().eq("table_id", tableId));
|
||||
delete(new LambdaQueryWrapperX<CodegenColumnDO>()
|
||||
.eq(CodegenColumnDO::getTableId, tableId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,24 +2,30 @@ package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CodegenTableMapper extends BaseMapperX<CodegenTableDO> {
|
||||
|
||||
default CodegenTableDO selectByTableName(String tableName) {
|
||||
return selectOne(new QueryWrapper<CodegenTableDO>().eq("table_name", tableName));
|
||||
default CodegenTableDO selectByTableNameAndDataSourceConfigId(String tableName, Long dataSourceConfigId) {
|
||||
return selectOne(CodegenTableDO::getTableName, tableName,
|
||||
CodegenTableDO::getDataSourceConfigId, dataSourceConfigId);
|
||||
}
|
||||
|
||||
default PageResult<CodegenTableDO> selectPage(CodegenTablePageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new QueryWrapperX<CodegenTableDO>()
|
||||
.likeIfPresent("table_name", pageReqVO.getTableName())
|
||||
.likeIfPresent("table_comment", pageReqVO.getTableComment())
|
||||
.betweenIfPresent("create_time", pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime()));
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<CodegenTableDO>()
|
||||
.likeIfPresent(CodegenTableDO::getTableName, pageReqVO.getTableName())
|
||||
.likeIfPresent(CodegenTableDO::getTableComment, pageReqVO.getTableComment())
|
||||
.betweenIfPresent(CodegenTableDO::getCreateTime, pageReqVO.getBeginCreateTime(), pageReqVO.getEndCreateTime()));
|
||||
}
|
||||
|
||||
default List<CodegenTableDO> selectListByDataSourceConfigId(Long dataSourceConfigId) {
|
||||
return selectList(CodegenTableDO::getDataSourceConfigId, dataSourceConfigId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,19 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SchemaColumnMapper extends BaseMapperX<SchemaColumnDO> {
|
||||
|
||||
default List<SchemaColumnDO> selectListByTableName(String tableSchema, String tableName) {
|
||||
return selectList(new QueryWrapper<SchemaColumnDO>().eq("table_name", tableName)
|
||||
.eq("table_schema", tableSchema)
|
||||
.orderByAsc("ordinal_position"));
|
||||
}
|
||||
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.mysql.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SchemaTableMapper extends BaseMapperX<SchemaTableDO> {
|
||||
|
||||
default List<SchemaTableDO> selectList(Collection<String> tableSchemas, String tableName, String tableComment) {
|
||||
return selectList(new QueryWrapperX<SchemaTableDO>().in("table_schema", tableSchemas)
|
||||
.likeIfPresent("table_name", tableName)
|
||||
.likeIfPresent("table_comment", tableComment));
|
||||
}
|
||||
|
||||
default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) {
|
||||
return selectOne(new QueryWrapper<SchemaTableDO>().eq("table_schema",tableSchema)
|
||||
.eq("table_name", tableName));
|
||||
}
|
||||
|
||||
}
|
@@ -2,12 +2,10 @@ package cn.iocoder.yudao.module.infra.dal.mysql.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.apollo.internals.ConfigFrameworkDAO;
|
||||
import cn.iocoder.yudao.framework.apollo.internals.dto.ConfigRespDTO;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -26,14 +24,18 @@ public class ConfigDAOImpl implements ConfigFrameworkDAO {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
|
||||
return jdbcTemplate.query("SELECT id FROM infra_config WHERE update_time > ? LIMIT 1",
|
||||
ResultSet::next, maxUpdateTime);
|
||||
public int selectCountByUpdateTimeGt(Date maxUpdateTime) {
|
||||
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM infra_config WHERE update_time > ?",
|
||||
Integer.class, maxUpdateTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigRespDTO> selectList() {
|
||||
return jdbcTemplate.query("SELECT `key`, `value`, update_time, deleted FROM infra_config", new BeanPropertyRowMapper<>(ConfigRespDTO.class));
|
||||
return jdbcTemplate.query("SELECT config_key, value, update_time, deleted FROM infra_config",
|
||||
(rs, rowNum) -> new ConfigRespDTO().setKey(rs.getString("config_key"))
|
||||
.setValue(rs.getString("value"))
|
||||
.setUpdateTime(rs.getDate("update_time"))
|
||||
.setDeleted(rs.getBoolean("deleted")));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,11 +2,10 @@ package cn.iocoder.yudao.module.infra.dal.mysql.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
@@ -15,23 +14,23 @@ import java.util.List;
|
||||
public interface ConfigMapper extends BaseMapperX<ConfigDO> {
|
||||
|
||||
default ConfigDO selectByKey(String key) {
|
||||
return selectOne(new QueryWrapper<ConfigDO>().eq("`key`", key));
|
||||
return selectOne(ConfigDO::getConfigKey, key);
|
||||
}
|
||||
|
||||
default PageResult<ConfigDO> selectPage(ConfigPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<ConfigDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.likeIfPresent("`key`", reqVO.getKey())
|
||||
.eqIfPresent("`type`", reqVO.getType())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<ConfigDO>()
|
||||
.likeIfPresent(ConfigDO::getName, reqVO.getName())
|
||||
.likeIfPresent(ConfigDO::getConfigKey, reqVO.getKey())
|
||||
.eqIfPresent(ConfigDO::getType, reqVO.getType())
|
||||
.betweenIfPresent(ConfigDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
}
|
||||
|
||||
default List<ConfigDO> selectList(ConfigExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<ConfigDO>()
|
||||
.likeIfPresent("name", reqVO.getName())
|
||||
.likeIfPresent("`key`", reqVO.getKey())
|
||||
.eqIfPresent("`type`", reqVO.getType())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
return selectList(new LambdaQueryWrapperX<ConfigDO>()
|
||||
.likeIfPresent(ConfigDO::getName, reqVO.getName())
|
||||
.likeIfPresent(ConfigDO::getConfigKey, reqVO.getKey())
|
||||
.eqIfPresent(ConfigDO::getType, reqVO.getType())
|
||||
.betweenIfPresent(ConfigDO::getCreateTime, reqVO.getBeginTime(), reqVO.getEndTime()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.infra.dal.mysql.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 数据源配置 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface DataSourceConfigMapper extends BaseMapperX<DataSourceConfigDO> {
|
||||
}
|
@@ -26,7 +26,7 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
||||
.orderByDesc(FileConfigDO::getId));
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM infra_file_config WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
@Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.mysql.file;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -16,11 +16,11 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
public interface FileMapper extends BaseMapperX<FileDO> {
|
||||
|
||||
default PageResult<FileDO> selectPage(FilePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<FileDO>()
|
||||
.likeIfPresent("path", reqVO.getPath())
|
||||
.likeIfPresent("type", reqVO.getType())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("create_time"));
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<FileDO>()
|
||||
.likeIfPresent(FileDO::getPath, reqVO.getPath())
|
||||
.likeIfPresent(FileDO::getType, reqVO.getType())
|
||||
.betweenIfPresent(FileDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc(FileDO::getId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,23 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.enums.codegen;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 代码生成的导入类型
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum CodegenImportTypeEnum {
|
||||
|
||||
DB(1), // 从 information_schema 的 table 和 columns 表导入
|
||||
SQL(2); // 基于建表 SQL 语句导入
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
|
||||
}
|
@@ -1,11 +1,12 @@
|
||||
package cn.iocoder.yudao.module.infra.service.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -17,32 +18,14 @@ import java.util.Map;
|
||||
*/
|
||||
public interface CodegenService {
|
||||
|
||||
/**
|
||||
* 基于 SQL 建表语句,创建代码生成器的表定义
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param sql SQL 建表语句
|
||||
* @return 创建的表定义的编号
|
||||
*/
|
||||
Long createCodegenListFromSQL(Long userId, String sql);
|
||||
|
||||
/**
|
||||
* 基于数据库的表结构,创建代码生成器的表定义
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param tableName 表名称
|
||||
* @return 创建的表定义的编号
|
||||
*/
|
||||
Long createCodegen(Long userId, String tableName);
|
||||
|
||||
/**
|
||||
* 基于 {@link #createCodegen(Long, String)} 的批量创建
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param tableNames 表名称数组
|
||||
* @param reqVO 表信息
|
||||
* @return 创建的表定义的编号数组
|
||||
*/
|
||||
List<Long> createCodegenListFromDB(Long userId, List<String> tableNames);
|
||||
List<Long> createCodegenList(Long userId, CodegenCreateListReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 更新数据库的表和字段定义
|
||||
@@ -58,14 +41,6 @@ public interface CodegenService {
|
||||
*/
|
||||
void syncCodegenFromDB(Long tableId);
|
||||
|
||||
/**
|
||||
* 基于 SQL 建表语句,同步数据库的表和字段定义
|
||||
*
|
||||
* @param tableId 表编号
|
||||
* @param sql SQL 建表语句
|
||||
*/
|
||||
void syncCodegenFromSQL(Long tableId, String sql);
|
||||
|
||||
/**
|
||||
* 删除数据库的表和字段定义
|
||||
*
|
||||
@@ -89,13 +64,6 @@ public interface CodegenService {
|
||||
*/
|
||||
CodegenTableDO getCodegenTablePage(Long id);
|
||||
|
||||
/**
|
||||
* 获得全部表定义
|
||||
*
|
||||
* @return 表定义数组
|
||||
*/
|
||||
List<CodegenTableDO> getCodeGenTableList();
|
||||
|
||||
/**
|
||||
* 获得指定表的字段定义数组
|
||||
*
|
||||
@@ -115,10 +83,12 @@ public interface CodegenService {
|
||||
/**
|
||||
* 获得数据库自带的表定义列表
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @param tableComment 表描述
|
||||
*
|
||||
* @param dataSourceConfigId 数据源的配置编号
|
||||
* @param name 表名称
|
||||
* @param comment 表描述
|
||||
* @return 表定义列表
|
||||
*/
|
||||
List<SchemaTableDO> getSchemaTableList(String tableName, String tableComment);
|
||||
List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment);
|
||||
|
||||
}
|
||||
|
@@ -1,26 +1,25 @@
|
||||
package cn.iocoder.yudao.module.infra.service.codegen;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaColumnMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaTableMapper;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenImportTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser;
|
||||
import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import org.apache.commons.collections4.KeyValue;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableField;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -43,9 +42,8 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
|
||||
public class CodegenServiceImpl implements CodegenService {
|
||||
|
||||
@Resource
|
||||
private SchemaTableMapper schemaTableMapper;
|
||||
@Resource
|
||||
private SchemaColumnMapper schemaColumnMapper;
|
||||
private DatabaseTableService databaseTableService;
|
||||
|
||||
@Resource
|
||||
private CodegenTableMapper codegenTableMapper;
|
||||
@Resource
|
||||
@@ -59,68 +57,63 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
@Resource
|
||||
private CodegenEngine codegenEngine;
|
||||
|
||||
@Resource
|
||||
private CodegenProperties codegenProperties;
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<Long> createCodegenList(Long userId, CodegenCreateListReqVO reqVO) {
|
||||
List<Long> ids = new ArrayList<>(reqVO.getTableNames().size());
|
||||
// 遍历添加。虽然效率会低一点,但是没必要做成完全批量,因为不会这么大量
|
||||
reqVO.getTableNames().forEach(tableName -> ids.add(createCodegen(userId, reqVO.getDataSourceConfigId(), tableName)));
|
||||
return ids;
|
||||
}
|
||||
|
||||
private Long createCodegen0(Long userId, CodegenImportTypeEnum importType,
|
||||
SchemaTableDO schemaTable, List<SchemaColumnDO> schemaColumns) {
|
||||
public Long createCodegen(Long userId, Long dataSourceConfigId, String tableName) {
|
||||
// 从数据库中,获得数据库表结构
|
||||
TableInfo tableInfo = databaseTableService.getTable(dataSourceConfigId, tableName);
|
||||
// 导入
|
||||
return createCodegen0(userId, dataSourceConfigId, tableInfo);
|
||||
}
|
||||
|
||||
private Long createCodegen0(Long userId, Long dataSourceConfigId, TableInfo tableInfo) {
|
||||
// 校验导入的表和字段非空
|
||||
if (schemaTable == null) {
|
||||
throw exception(CODEGEN_IMPORT_TABLE_NULL);
|
||||
}
|
||||
if (CollUtil.isEmpty(schemaColumns)) {
|
||||
throw exception(CODEGEN_IMPORT_COLUMNS_NULL);
|
||||
}
|
||||
checkTableInfo(tableInfo);
|
||||
// 校验是否已经存在
|
||||
if (codegenTableMapper.selectByTableName(schemaTable.getTableName()) != null) {
|
||||
if (codegenTableMapper.selectByTableNameAndDataSourceConfigId(tableInfo.getName(),
|
||||
dataSourceConfigId) != null) {
|
||||
throw exception(CODEGEN_TABLE_EXISTS);
|
||||
}
|
||||
|
||||
// 构建 CodegenTableDO 对象,插入到 DB 中
|
||||
CodegenTableDO table = codegenBuilder.buildTable(schemaTable);
|
||||
table.setImportType(importType.getType());
|
||||
CodegenTableDO table = codegenBuilder.buildTable(tableInfo);
|
||||
table.setDataSourceConfigId(dataSourceConfigId);
|
||||
table.setScene(CodegenSceneEnum.ADMIN.getScene()); // 默认配置下,使用管理后台的模板
|
||||
table.setAuthor(userApi.getUser(userId).getNickname());
|
||||
codegenTableMapper.insert(table);
|
||||
|
||||
// 构建 CodegenColumnDO 数组,插入到 DB 中
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(table.getId(), schemaColumns);
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(table.getId(), tableInfo.getFields());
|
||||
// 如果没有主键,则使用第一个字段作为主键
|
||||
if (!tableInfo.isHavePrimaryKey()) {
|
||||
columns.get(0).setPrimaryKey(true);
|
||||
}
|
||||
codegenColumnMapper.insertBatch(columns);
|
||||
return table.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createCodegenListFromSQL(Long userId, String sql) {
|
||||
// 从 SQL 中,获得数据库表结构
|
||||
SchemaTableDO schemaTable;
|
||||
List<SchemaColumnDO> schemaColumns;
|
||||
try {
|
||||
KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql);
|
||||
schemaTable = result.getKey();
|
||||
schemaColumns = result.getValue();
|
||||
} catch (Exception ex) {
|
||||
throw exception(CODEGEN_PARSE_SQL_ERROR);
|
||||
private void checkTableInfo(TableInfo tableInfo) {
|
||||
if (tableInfo == null) {
|
||||
throw exception(CODEGEN_IMPORT_TABLE_NULL);
|
||||
}
|
||||
// 导入
|
||||
return this.createCodegen0(userId, CodegenImportTypeEnum.SQL, schemaTable, schemaColumns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createCodegen(Long userId, String tableName) {
|
||||
// 获取当前schema
|
||||
String tableSchema = codegenProperties.getDbSchemas().iterator().next();
|
||||
// 从数据库中,获得数据库表结构
|
||||
SchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName);
|
||||
List<SchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName);
|
||||
// 导入
|
||||
return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<Long> createCodegenListFromDB(Long userId, List<String> tableNames) {
|
||||
List<Long> ids = new ArrayList<>(tableNames.size());
|
||||
// 遍历添加。虽然效率会低一点,但是没必要做成完全批量,因为不会这么大量
|
||||
tableNames.forEach(tableName -> ids.add(createCodegen(userId, tableName)));
|
||||
return ids;
|
||||
if (StrUtil.isEmpty(tableInfo.getComment())) {
|
||||
throw exception(CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL);
|
||||
}
|
||||
if (CollUtil.isEmpty(tableInfo.getFields())) {
|
||||
throw exception(CODEGEN_IMPORT_COLUMNS_NULL);
|
||||
}
|
||||
tableInfo.getFields().forEach(field -> {
|
||||
if (StrUtil.isEmpty(field.getComment())) {
|
||||
throw exception(CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL, field.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,56 +140,32 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
if (table == null) {
|
||||
throw exception(CODEGEN_TABLE_NOT_EXISTS);
|
||||
}
|
||||
String tableSchema = codegenProperties.getDbSchemas().iterator().next();
|
||||
// 从数据库中,获得数据库表结构
|
||||
List<SchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName());
|
||||
|
||||
TableInfo tableInfo = databaseTableService.getTable(table.getDataSourceConfigId(), table.getTableName());
|
||||
// 执行同步
|
||||
this.syncCodegen0(tableId, schemaColumns);
|
||||
syncCodegen0(tableId, tableInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncCodegenFromSQL(Long tableId, String sql) {
|
||||
// 校验是否已经存在
|
||||
CodegenTableDO table = codegenTableMapper.selectById(tableId);
|
||||
if (table == null) {
|
||||
throw exception(CODEGEN_TABLE_NOT_EXISTS);
|
||||
}
|
||||
// 从 SQL 中,获得数据库表结构
|
||||
List<SchemaColumnDO> schemaColumns;
|
||||
try {
|
||||
KeyValue<SchemaTableDO, List<SchemaColumnDO>> result = CodegenSQLParser.parse(sql);
|
||||
schemaColumns = result.getValue();
|
||||
} catch (Exception ex) {
|
||||
throw exception(CODEGEN_PARSE_SQL_ERROR);
|
||||
}
|
||||
|
||||
// 执行同步
|
||||
this.syncCodegen0(tableId, schemaColumns);
|
||||
}
|
||||
|
||||
private void syncCodegen0(Long tableId, List<SchemaColumnDO> schemaColumns) {
|
||||
// 校验导入的字段不为空
|
||||
if (CollUtil.isEmpty(schemaColumns)) {
|
||||
throw exception(CODEGEN_SYNC_COLUMNS_NULL);
|
||||
}
|
||||
Set<String> schemaColumnNames = CollectionUtils.convertSet(schemaColumns, SchemaColumnDO::getColumnName);
|
||||
private void syncCodegen0(Long tableId, TableInfo tableInfo) {
|
||||
// 校验导入的表和字段非空
|
||||
checkTableInfo(tableInfo);
|
||||
List<TableField> tableFields = tableInfo.getFields();
|
||||
|
||||
// 构建 CodegenColumnDO 数组,只同步新增的字段
|
||||
List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId);
|
||||
Set<String> codegenColumnNames = CollectionUtils.convertSet(codegenColumns, CodegenColumnDO::getColumnName);
|
||||
// 移除已经存在的字段
|
||||
schemaColumns.removeIf(column -> codegenColumnNames.contains(column.getColumnName()));
|
||||
tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName()));
|
||||
// 计算需要删除的字段
|
||||
Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !schemaColumnNames.contains(column.getColumnName()))
|
||||
Set<String> tableFieldNames = CollectionUtils.convertSet(tableFields, TableField::getName);
|
||||
Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !tableFieldNames.contains(column.getColumnName()))
|
||||
.map(CodegenColumnDO::getId).collect(Collectors.toSet());
|
||||
if (CollUtil.isEmpty(schemaColumns) && CollUtil.isEmpty(deleteColumnIds)) {
|
||||
if (CollUtil.isEmpty(tableFields) && CollUtil.isEmpty(deleteColumnIds)) {
|
||||
throw exception(CODEGEN_SYNC_NONE_CHANGE);
|
||||
}
|
||||
|
||||
// 插入新增的字段
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(tableId, schemaColumns);
|
||||
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(tableId, tableFields);
|
||||
codegenColumnMapper.insertBatch(columns);
|
||||
// 删除不存在的字段
|
||||
if (CollUtil.isNotEmpty(deleteColumnIds)) {
|
||||
@@ -228,11 +197,6 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
return codegenTableMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CodegenTableDO> getCodeGenTableList() {
|
||||
return codegenTableMapper.selectList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CodegenColumnDO> getCodegenColumnListByTableId(Long tableId) {
|
||||
return codegenColumnMapper.selectListByTableId(tableId);
|
||||
@@ -255,13 +219,18 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SchemaTableDO> getSchemaTableList(String tableName, String tableComment) {
|
||||
List<SchemaTableDO> tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment);
|
||||
// TODO 强制移除 Quartz 的表,未来做成可配置
|
||||
tables.removeIf(table -> table.getTableName().startsWith("QRTZ_"));
|
||||
tables.removeIf(table -> table.getTableName().startsWith("ACT_"));
|
||||
tables.removeIf(table -> table.getTableName().startsWith("FLW_"));
|
||||
return tables;
|
||||
public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) {
|
||||
List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment);
|
||||
// 移除置顶前缀的表名 // TODO 未来做成可配置
|
||||
tables.removeIf(table -> table.getName().toUpperCase().startsWith("QRTZ_"));
|
||||
tables.removeIf(table -> table.getName().toUpperCase().startsWith("ACT_"));
|
||||
tables.removeIf(table -> table.getName().toUpperCase().startsWith("FLW_"));
|
||||
// 移除已经生成的表
|
||||
// 移除在 Codegen 中,已经存在的
|
||||
Set<String> existsTables = CollectionUtils.convertSet(
|
||||
codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName);
|
||||
tables.removeIf(table -> existsTables.contains(table.getName()));
|
||||
return CodegenConvert.INSTANCE.convertList04(tables);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -7,23 +7,22 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableField;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.hutool.core.text.CharSequenceUtil.*;
|
||||
|
||||
/**
|
||||
* 代码生成器的 Builder,负责:
|
||||
* 1. 将数据库的表 {@link SchemaTableDO} 定义,构建成 {@link CodegenTableDO}
|
||||
* 2. 将数据库的列 {@link SchemaColumnDO} 构定义,建成 {@link CodegenColumnDO}
|
||||
* 1. 将数据库的表 {@link TableInfo} 定义,构建成 {@link CodegenTableDO}
|
||||
* 2. 将数据库的列 {@link TableField} 构定义,建成 {@link CodegenColumnDO}
|
||||
*/
|
||||
@Component
|
||||
public class CodegenBuilder {
|
||||
@@ -82,21 +81,6 @@ public class CodegenBuilder {
|
||||
*/
|
||||
private static final Set<String> LIST_OPERATION_RESULT_EXCLUDE_COLUMN = Sets.newHashSet();
|
||||
|
||||
/**
|
||||
* Java 类型与 MySQL 类型的映射关系
|
||||
*/
|
||||
private static final Map<String, Set<String>> javaTypeMappings = MapUtil.<String, Set<String>>builder()
|
||||
.put(Boolean.class.getSimpleName(), Sets.newHashSet("bit"))
|
||||
.put(Integer.class.getSimpleName(), Sets.newHashSet("tinyint", "smallint", "mediumint", "int"))
|
||||
.put(Long.class.getSimpleName(), Collections.singleton("bigint"))
|
||||
.put(Double.class.getSimpleName(), Sets.newHashSet("float", "double"))
|
||||
.put(BigDecimal.class.getSimpleName(), Sets.newHashSet("decimal", "numeric"))
|
||||
.put(String.class.getSimpleName(), Sets.newHashSet("tinytext", "text", "mediumtext", "longtext", // 长文本
|
||||
"char", "varchar", "nvarchar", "varchar2")) // 短文本
|
||||
.put(Date.class.getSimpleName(), Sets.newHashSet("datetime", "time", "date", "timestamp"))
|
||||
.put("byte[]", Sets.newHashSet("blob"))
|
||||
.build();
|
||||
|
||||
static {
|
||||
Arrays.stream(ReflectUtil.getFields(BaseDO.class)).forEach(field -> BASE_DO_FIELDS.add(field.getName()));
|
||||
BASE_DO_FIELDS.add(TENANT_ID_FIELD);
|
||||
@@ -109,8 +93,8 @@ public class CodegenBuilder {
|
||||
LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的
|
||||
}
|
||||
|
||||
public CodegenTableDO buildTable(SchemaTableDO schemaTable) {
|
||||
CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable);
|
||||
public CodegenTableDO buildTable(TableInfo tableInfo) {
|
||||
CodegenTableDO table = CodegenConvert.INSTANCE.convert(tableInfo);
|
||||
initTableDefault(table);
|
||||
return table;
|
||||
}
|
||||
@@ -121,57 +105,33 @@ public class CodegenBuilder {
|
||||
* @param table 表定义
|
||||
*/
|
||||
private void initTableDefault(CodegenTableDO table) {
|
||||
// 以 system_dept 举例子。moduleName 为 system、businessName 为 dept、className 为 SystemDept
|
||||
// 如果不希望 System 前缀,则可以手动在【代码生成 - 修改生成配置 - 基本信息】,将实体类名称改为 Dept 即可
|
||||
table.setModuleName(subBefore(table.getTableName(), '_', false)); // 第一个 _ 前缀的前面,作为 module 名字
|
||||
table.setBusinessName(toCamelCase(subAfter(table.getTableName(),
|
||||
'_', false))); // 第一步,第一个 _ 前缀的后面,作为 module 名字; 第二步,可能存在多个 _ 的情况,转换成驼峰
|
||||
table.setClassName(upperFirst(toCamelCase( // 驼峰 + 首字母大写
|
||||
subAfter(table.getTableName(), '_', false)))); // 第一个 _ 前缀的前面,作为 class 名字
|
||||
table.setClassComment(subBefore(table.getTableComment(), // 去除结尾的表,作为类描述
|
||||
'表', true));
|
||||
// 以 system_dept 举例子。moduleName 为 system、businessName 为 dept、className 为 Dept
|
||||
// 如果希望以 System 前缀,则可以手动在【代码生成 - 修改生成配置 - 基本信息】,将实体类名称改为 SystemDept 即可
|
||||
String tableName = table.getTableName().toLowerCase();
|
||||
// 第一步,_ 前缀的前面,作为 module 名字;第二步,moduleName 必须小写;
|
||||
table.setModuleName(subBefore(tableName, '_', false).toLowerCase());
|
||||
// 第一步,第一个 _ 前缀的后面,作为 module 名字; 第二步,可能存在多个 _ 的情况,转换成驼峰; 第三步,businessName 必须小写;
|
||||
table.setBusinessName(toCamelCase(subAfter(tableName, '_', false)).toLowerCase());
|
||||
// 驼峰 + 首字母大写;第一步,第一个 _ 前缀的后面,作为 class 名字;第二步,驼峰命名
|
||||
table.setClassName(upperFirst(toCamelCase(subAfter(tableName, '_', false))));
|
||||
// 去除结尾的表,作为类描述
|
||||
table.setClassComment(StrUtil.removeSuffixIgnoreCase(table.getTableComment(), "表"));
|
||||
table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType());
|
||||
}
|
||||
|
||||
public List<CodegenColumnDO> buildColumns(Long tableId, List<SchemaColumnDO> schemaColumns) {
|
||||
List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(schemaColumns);
|
||||
public List<CodegenColumnDO> buildColumns(Long tableId, List<TableField> tableFields) {
|
||||
List<CodegenColumnDO> columns = CodegenConvert.INSTANCE.convertList(tableFields);
|
||||
int index = 1;
|
||||
for (CodegenColumnDO column : columns) {
|
||||
column.setTableId(tableId);
|
||||
initColumnDefault(column);
|
||||
column.setOrdinalPosition(index++);
|
||||
// 初始化 Column 列的默认字段
|
||||
processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
|
||||
processColumnUI(column); // 处理 UI 相关的字段的默认值
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 Column 列的默认字段
|
||||
*
|
||||
* @param column 列定义
|
||||
*/
|
||||
private void initColumnDefault(CodegenColumnDO column) {
|
||||
// 处理 Java 相关的字段的默认值
|
||||
processColumnJava(column);
|
||||
// 处理 CRUD 相关的字段的默认值
|
||||
processColumnOperation(column);
|
||||
// 处理 UI 相关的字段的默认值
|
||||
processColumnUI(column);
|
||||
}
|
||||
|
||||
private void processColumnJava(CodegenColumnDO column) {
|
||||
// 处理 javaField 字段
|
||||
column.setJavaField(toCamelCase(column.getColumnName()));
|
||||
// 处理 dictType 字段,暂无
|
||||
// 处理 javaType 字段(兼容无符号类型)
|
||||
String dbType = replaceIgnoreCase(subBefore(column.getColumnType(), '(', false),
|
||||
" UNSIGNED", "");
|
||||
javaTypeMappings.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().contains(dbType))
|
||||
.findFirst().ifPresent(entry -> column.setJavaType(entry.getKey()));
|
||||
if (column.getJavaType() == null) {
|
||||
throw new IllegalStateException(String.format("column(%s) 的数据库类型(%s) 找不到匹配的 Java 类型",
|
||||
column.getColumnName(), column.getColumnType()));
|
||||
}
|
||||
}
|
||||
|
||||
private void processColumnOperation(CodegenColumnDO column) {
|
||||
// 处理 createOperation 字段
|
||||
column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField())
|
||||
|
@@ -217,7 +217,7 @@ public class CodegenEngine {
|
||||
private static String mapperXmlFilePath() {
|
||||
return "yudao-module-${table.moduleName}/" + // 顶级模块
|
||||
"yudao-module-${table.moduleName}-biz/" + // 子模块
|
||||
"src/main/java/resources/mapper/${table.businessName}/${table.className}Mapper.xml";
|
||||
"src/main/resources/mapper/${table.businessName}/${table.className}Mapper.xml";
|
||||
}
|
||||
|
||||
private static String vueTemplatePath(String path) {
|
||||
|
@@ -1,117 +0,0 @@
|
||||
package cn.iocoder.yudao.module.infra.service.codegen.inner;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO;
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
|
||||
import com.alibaba.druid.sql.repository.SchemaRepository;
|
||||
import org.apache.commons.collections4.KeyValue;
|
||||
import org.apache.commons.collections4.keyvalue.DefaultKeyValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.alibaba.druid.sql.SQLUtils.normalize;
|
||||
|
||||
/**
|
||||
* SQL 解析器,将创建表的 SQL,解析成 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象,
|
||||
* 后续可以基于它们,生成代码~
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class CodegenSQLParser {
|
||||
|
||||
/**
|
||||
* 解析建表 SQL 语句,返回 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象
|
||||
*
|
||||
* @param sql 建表 SQL 语句
|
||||
* @return 解析结果
|
||||
*/
|
||||
public static KeyValue<SchemaTableDO, List<SchemaColumnDO>> parse(String sql) {
|
||||
// 解析 SQL 成 Statement
|
||||
SQLCreateTableStatement statement = parseCreateSQL(sql);
|
||||
// 解析 Table 表
|
||||
SchemaTableDO table = parseTable(statement);
|
||||
// 解析 Column 字段
|
||||
List<SchemaColumnDO> columns = parseColumns(statement);
|
||||
columns.forEach(column -> column.setTableName(table.getTableName()));
|
||||
// 返回
|
||||
return new DefaultKeyValue<>(table, columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 Druid 工具,建表 SQL 语句
|
||||
*
|
||||
* @param sql 建表 SQL 语句
|
||||
* @return 创建 Statement
|
||||
*/
|
||||
private static SQLCreateTableStatement parseCreateSQL(String sql) {
|
||||
// 解析 SQL
|
||||
SchemaRepository repository = new SchemaRepository(DbType.mysql);
|
||||
repository.console(sql);
|
||||
// 获得该表对应的 MySqlCreateTableStatement 对象
|
||||
String tableName = CollUtil.getFirst(repository.getDefaultSchema().getObjects()).getName();
|
||||
return (MySqlCreateTableStatement) repository.findTable(tableName).getStatement();
|
||||
}
|
||||
|
||||
private static SchemaTableDO parseTable(SQLCreateTableStatement statement) {
|
||||
return SchemaTableDO.builder()
|
||||
.tableName(statement.getTableSource().getTableName(true))
|
||||
.tableComment(getCommentText(statement))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static String getCommentText(SQLCreateTableStatement statement) {
|
||||
if (statement == null || statement.getComment() == null) {
|
||||
return "";
|
||||
}
|
||||
return ((SQLCharExpr) statement.getComment()).getText();
|
||||
}
|
||||
|
||||
private static List<SchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {
|
||||
List<SchemaColumnDO> columns = new ArrayList<>();
|
||||
statement.getTableElementList().forEach(element -> parseColumn(columns, element));
|
||||
return columns;
|
||||
}
|
||||
|
||||
private static void parseColumn(List<SchemaColumnDO> columns, SQLTableElement element) {
|
||||
// 处理主键
|
||||
if (element instanceof SQLPrimaryKey) {
|
||||
parsePrimaryKey(columns, (SQLPrimaryKey) element);
|
||||
return;
|
||||
}
|
||||
// 处理字段定义
|
||||
if (element instanceof SQLColumnDefinition) {
|
||||
parseColumnDefinition(columns, (SQLColumnDefinition) element);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parsePrimaryKey(List<SchemaColumnDO> columns, SQLPrimaryKey primaryKey) {
|
||||
String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键
|
||||
// 匹配 columns 主键字段,设置为 primary
|
||||
columns.stream().filter(column -> column.getColumnName().equals(columnName))
|
||||
.forEach(column -> column.setPrimaryKey(true));
|
||||
}
|
||||
|
||||
private static void parseColumnDefinition(List<SchemaColumnDO> columns, SQLColumnDefinition definition) {
|
||||
String text = definition.toString().toUpperCase();
|
||||
columns.add(SchemaColumnDO.builder()
|
||||
.columnName(normalize(definition.getColumnName()))
|
||||
.columnType(definition.getDataType().toString())
|
||||
.columnComment(Objects.isNull(definition.getComment()) ? ""
|
||||
: normalize(definition.getComment().toString()))
|
||||
.nullable(!text.contains(" NOT NULL"))
|
||||
.primaryKey(false)
|
||||
.autoIncrement(text.contains("AUTO_INCREMENT"))
|
||||
.ordinalPosition(columns.size() + 1)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.infra.service.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO;
|
||||
@@ -96,7 +97,9 @@ public class ConfigServiceImpl implements ConfigService {
|
||||
// 校验自己存在
|
||||
checkConfigExists(id);
|
||||
// 校验参数配置 key 的唯一性
|
||||
checkConfigKeyUnique(id, key);
|
||||
if (StrUtil.isNotEmpty(key)) {
|
||||
checkConfigKeyUnique(id, key);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
@@ -0,0 +1,54 @@
|
||||
package cn.iocoder.yudao.module.infra.service.db;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据源配置 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface DataSourceConfigService {
|
||||
|
||||
/**
|
||||
* 创建数据源配置
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createDataSourceConfig(@Valid DataSourceConfigCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新数据源配置
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateDataSourceConfig(@Valid DataSourceConfigUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除数据源配置
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteDataSourceConfig(Long id);
|
||||
|
||||
/**
|
||||
* 获得数据源配置
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 数据源配置
|
||||
*/
|
||||
DataSourceConfigDO getDataSourceConfig(Long id);
|
||||
|
||||
/**
|
||||
* 获得数据源配置列表
|
||||
*
|
||||
* @return 数据源配置列表
|
||||
*/
|
||||
List<DataSourceConfigDO> getDataSourceConfigList();
|
||||
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
package cn.iocoder.yudao.module.infra.service.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import org.jasypt.encryption.StringEncryptor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_OK;
|
||||
|
||||
/**
|
||||
* 数据源配置 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class DataSourceConfigServiceImpl implements DataSourceConfigService {
|
||||
|
||||
@Resource
|
||||
private DataSourceConfigMapper dataSourceConfigMapper;
|
||||
|
||||
@Resource
|
||||
private StringEncryptor stringEncryptor;
|
||||
|
||||
@Resource
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
||||
|
||||
@Override
|
||||
public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) {
|
||||
DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO);
|
||||
checkConnectionOK(dataSourceConfig);
|
||||
|
||||
// 插入
|
||||
dataSourceConfig.setPassword(stringEncryptor.encrypt(createReqVO.getPassword()));
|
||||
dataSourceConfigMapper.insert(dataSourceConfig);
|
||||
// 返回
|
||||
return dataSourceConfig.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDataSourceConfig(DataSourceConfigUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateDataSourceConfigExists(updateReqVO.getId());
|
||||
DataSourceConfigDO updateObj = DataSourceConfigConvert.INSTANCE.convert(updateReqVO);
|
||||
checkConnectionOK(updateObj);
|
||||
|
||||
// 更新
|
||||
updateObj.setPassword(stringEncryptor.encrypt(updateObj.getPassword()));
|
||||
dataSourceConfigMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDataSourceConfig(Long id) {
|
||||
// 校验存在
|
||||
validateDataSourceConfigExists(id);
|
||||
// 删除
|
||||
dataSourceConfigMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateDataSourceConfigExists(Long id) {
|
||||
if (dataSourceConfigMapper.selectById(id) == null) {
|
||||
throw exception(DATA_SOURCE_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceConfigDO getDataSourceConfig(Long id) {
|
||||
// 如果 id 为 0,默认为 master 的数据源
|
||||
if (Objects.equals(id, DataSourceConfigDO.ID_MASTER)) {
|
||||
return buildMasterDataSourceConfig();
|
||||
}
|
||||
// 从 DB 中读取
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id);
|
||||
try {
|
||||
dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword()));
|
||||
} catch (Exception ignore) { // 解码失败,则不解码
|
||||
}
|
||||
return dataSourceConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataSourceConfigDO> getDataSourceConfigList() {
|
||||
List<DataSourceConfigDO> result = dataSourceConfigMapper.selectList();
|
||||
// 补充 master 数据源
|
||||
result.add(0, buildMasterDataSourceConfig());
|
||||
return result;
|
||||
}
|
||||
|
||||
private void checkConnectionOK(DataSourceConfigDO config) {
|
||||
boolean success = JdbcUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword());
|
||||
if (!success) {
|
||||
throw exception(DATA_SOURCE_CONFIG_NOT_OK);
|
||||
}
|
||||
}
|
||||
|
||||
private DataSourceConfigDO buildMasterDataSourceConfig() {
|
||||
String primary = dynamicDataSourceProperties.getPrimary();
|
||||
DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary);
|
||||
return new DataSourceConfigDO().setId(DataSourceConfigDO.ID_MASTER).setName(primary)
|
||||
.setUrl(dataSourceProperty.getUrl())
|
||||
.setUsername(dataSourceProperty.getUsername())
|
||||
.setPassword(dataSourceProperty.getPassword());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.infra.service.db;
|
||||
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据库表 Service
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface DatabaseTableService {
|
||||
|
||||
/**
|
||||
* 获得表列表,基于表名称 + 表描述进行模糊匹配
|
||||
*
|
||||
* @param dataSourceConfigId 数据源配置的编号
|
||||
* @param nameLike 表名称,模糊匹配
|
||||
* @param commentLike 表描述,模糊匹配
|
||||
* @return 表列表
|
||||
*/
|
||||
List<TableInfo> getTableList(Long dataSourceConfigId, String nameLike, String commentLike);
|
||||
|
||||
/**
|
||||
* 获得指定表名
|
||||
*
|
||||
* @param dataSourceConfigId 数据源配置的编号
|
||||
* @param tableName 表名称
|
||||
* @return 表
|
||||
*/
|
||||
TableInfo getTable(Long dataSourceConfigId, String tableName);
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package cn.iocoder.yudao.module.infra.service.db;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 数据库表 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class DatabaseTableServiceImpl implements DatabaseTableService {
|
||||
|
||||
@Resource
|
||||
private DataSourceConfigService dataSourceConfigService;
|
||||
|
||||
@Override
|
||||
public List<TableInfo> getTableList(Long dataSourceConfigId, String nameLike, String commentLike) {
|
||||
List<TableInfo> tables = getTableList0(dataSourceConfigId, null);
|
||||
return tables.stream().filter(tableInfo -> (StrUtil.isEmpty(nameLike) || tableInfo.getName().contains(nameLike))
|
||||
&& (StrUtil.isEmpty(commentLike) || tableInfo.getComment().contains(commentLike)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableInfo getTable(Long dataSourceConfigId, String name) {
|
||||
return CollUtil.getFirst(getTableList0(dataSourceConfigId, name));
|
||||
}
|
||||
|
||||
public List<TableInfo> getTableList0(Long dataSourceConfigId, String name) {
|
||||
// 获得数据源配置
|
||||
DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId);
|
||||
Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId);
|
||||
|
||||
// 使用 MyBatis Plus Generator 解析表结构
|
||||
DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(config.getUrl(), config.getUsername(),
|
||||
config.getPassword()).build();
|
||||
StrategyConfig.Builder strategyConfig = new StrategyConfig.Builder();
|
||||
if (StrUtil.isNotEmpty(name)) {
|
||||
strategyConfig.addInclude(name);
|
||||
}
|
||||
GlobalConfig globalConfig = new GlobalConfig.Builder().dateType(DateType.ONLY_DATE).build(); // 只使用 Date 类型,不使用 LocalDate
|
||||
ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, strategyConfig.build(),
|
||||
null, globalConfig, null);
|
||||
// 按照名字排序
|
||||
List<TableInfo> tables = builder.getTableInfoList();
|
||||
tables.sort(Comparator.comparing(TableInfo::getName));
|
||||
return tables;
|
||||
}
|
||||
|
||||
}
|
@@ -123,7 +123,7 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadFileConfigIfUpdate][首次加载全量文件配置]");
|
||||
} else { // 判断数据库中是否有更新的文件配置
|
||||
if (fileConfigMapper.selectExistsByUpdateTimeAfter(maxUpdateTime) == null) {
|
||||
if (fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
}
|
||||
log.info("[loadFileConfigIfUpdate][增量加载全量文件配置]");
|
||||
|
@@ -7,7 +7,7 @@ import javax.validation.constraints.*;
|
||||
## 处理 Date 字段的引入
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult})
|
||||
&& ${column.javaType} == "Date"))## 时间类型
|
||||
&& ${column.javaType} == "Date")## 时间类型
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
@@ -10,7 +10,8 @@ import ${BaseDOClassName};
|
||||
*
|
||||
* @author ${table.author}
|
||||
*/
|
||||
@TableName("${table.tableName}")
|
||||
@TableName("${table.tableName.toLowerCase()}")
|
||||
@KeySequence("${table.tableName.toLowerCase()}_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@@ -1,23 +1,34 @@
|
||||
-- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tables.sql 文件里
|
||||
CREATE TABLE IF NOT EXISTS "${table.tableName}" (
|
||||
CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" (
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.javaType} == 'Long')
|
||||
#set ($dataType='bigint')
|
||||
#elseif (${column.javaType} == 'Integer')
|
||||
#set ($dataType='int')
|
||||
#elseif (${column.javaType} == 'Boolean')
|
||||
#set ($dataType='bit')
|
||||
#elseif (${column.javaType} == 'Date')
|
||||
#set ($dataType='datetime')
|
||||
#else
|
||||
#set ($dataType='varchar')
|
||||
#end
|
||||
#if (${column.primaryKey})##处理主键
|
||||
"${column.javaField}"#if (${column.javaType} == 'String') ${column.columnType} NOT NULL#else ${column.columnType} NOT NULL GENERATED BY DEFAULT AS IDENTITY#end,
|
||||
"${column.javaField}"#if (${column.javaType} == 'String') ${dataType} NOT NULL#else ${dataType} NOT NULL GENERATED BY DEFAULT AS IDENTITY#end,
|
||||
#else
|
||||
#if (${column.columnName} == 'create_time')
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
#elseif (${column.columnName} == 'update_time')
|
||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
#elseif (${column.columnName} == 'creator' || ${column.columnName} == 'updater')
|
||||
"${column.columnName}" ${column.columnType} DEFAULT '',
|
||||
"${column.columnName}" ${dataType} DEFAULT '',
|
||||
#elseif (${column.columnName} == 'deleted')
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
#else
|
||||
"${column.columnName}" ${column.columnType}#if (${column.nullable} == false) NOT NULL#end,
|
||||
"${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end,
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
PRIMARY KEY ("${primaryColumn.columnName}")
|
||||
PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}")
|
||||
) COMMENT '${table.tableComment}';
|
||||
|
||||
-- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里
|
||||
|
@@ -1,7 +1,7 @@
|
||||
-- 菜单 SQL
|
||||
INSERT INTO `system_menu`(
|
||||
`name`, `permission`, `menu_type`, `sort`, `parent_id`,
|
||||
`path`, `icon`, `component`, `status`
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
|
||||
@@ -16,9 +16,9 @@ SELECT @parentId := LAST_INSERT_ID();
|
||||
#set ($functionOps = ['query', 'create', 'update', 'delete', 'export'])
|
||||
#foreach ($functionName in $functionNames)
|
||||
#set ($index = $foreach.count - 1)
|
||||
INSERT INTO `system_menu`(
|
||||
`name`, `permission`, `menu_type`, `sort`, `parent_id`,
|
||||
`path`, `icon`, `component`, `status`
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
)
|
||||
VALUES (
|
||||
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
|
||||
|
@@ -160,7 +160,7 @@
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")## 时间框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-date-picker clearable v-model="form.${javaField}" type="date" value-format="yyyy-MM-dd" placeholder="选择${comment}" />
|
||||
<el-date-picker clearable v-model="form.${javaField}" type="date" value-format="timestamp" placeholder="选择${comment}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "textarea")## 文本框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
@@ -390,7 +390,7 @@ export default {
|
||||
this.exportLoading = true;
|
||||
return export${simpleClassName}Excel(params);
|
||||
}).then(response => {
|
||||
this.$download.excel(response, "${table.classComment}.xls");
|
||||
this.#[[$]]#download.excel(response, '${table.classComment}.xls');
|
||||
this.exportLoading = false;
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.infra.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.generator.IDatabaseQuery.DefaultDatabaseQuery;
|
||||
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultDatabaseQueryTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder("jdbc:oracle:thin:@127.0.0.1:1521:xe",
|
||||
// "root", "123456").build();
|
||||
DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder("jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro",
|
||||
"root", "123456").build();
|
||||
// StrategyConfig strategyConfig = new StrategyConfig.Builder().build();
|
||||
|
||||
ConfigBuilder builder = new ConfigBuilder(null, dataSourceConfig, null, null, null, null);
|
||||
|
||||
DefaultDatabaseQuery query = new DefaultDatabaseQuery(builder);
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
List<TableInfo> tableInfos = query.queryTables();
|
||||
for (TableInfo tableInfo : tableInfos) {
|
||||
if (StrUtil.startWithAny(tableInfo.getName().toLowerCase(), "act_", "flw_", "qrtz_")) {
|
||||
continue;
|
||||
}
|
||||
// System.out.println(String.format("CREATE SEQUENCE %s_seq MINVALUE 0;", tableInfo.getName()));
|
||||
System.out.println(String.format("DELETE FROM %s WHERE deleted = '1';", tableInfo.getName()));
|
||||
}
|
||||
System.out.println(tableInfos.size());
|
||||
System.out.println(System.currentTimeMillis() - time);
|
||||
}
|
||||
|
||||
}
|
@@ -137,7 +137,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
// 准备参数
|
||||
String key = randomString();
|
||||
// mock 数据
|
||||
configMapper.insert(randomConfigDO(o -> o.setKey(key)));
|
||||
configMapper.insert(randomConfigDO(o -> o.setConfigKey(key)));
|
||||
|
||||
// 调用,校验异常
|
||||
assertServiceException(() -> configService.checkConfigKeyUnique(null, key),
|
||||
@@ -150,7 +150,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
Long id = randomLongId();
|
||||
String key = randomString();
|
||||
// mock 数据
|
||||
configMapper.insert(randomConfigDO(o -> o.setKey(key)));
|
||||
configMapper.insert(randomConfigDO(o -> o.setConfigKey(key)));
|
||||
|
||||
// 调用,校验异常
|
||||
assertServiceException(() -> configService.checkConfigKeyUnique(id, key),
|
||||
@@ -162,7 +162,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
// mock 数据
|
||||
ConfigDO dbConfig = randomConfigDO(o -> { // 等会查询到
|
||||
o.setName("芋艿");
|
||||
o.setKey("yunai");
|
||||
o.setConfigKey("yunai");
|
||||
o.setType(ConfigTypeEnum.SYSTEM.getType());
|
||||
o.setCreateTime(buildTime(2021, 2, 1));
|
||||
});
|
||||
@@ -170,7 +170,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
// 测试 name 不匹配
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setName("土豆")));
|
||||
// 测试 key 不匹配
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou")));
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setConfigKey("tudou")));
|
||||
// 测试 type 不匹配
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType())));
|
||||
// 测试 createTime 不匹配
|
||||
@@ -196,7 +196,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
// mock 数据
|
||||
ConfigDO dbConfig = randomConfigDO(o -> { // 等会查询到
|
||||
o.setName("芋艿");
|
||||
o.setKey("yunai");
|
||||
o.setConfigKey("yunai");
|
||||
o.setType(ConfigTypeEnum.SYSTEM.getType());
|
||||
o.setCreateTime(buildTime(2021, 2, 1));
|
||||
});
|
||||
@@ -204,7 +204,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
// 测试 name 不匹配
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setName("土豆")));
|
||||
// 测试 key 不匹配
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou")));
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setConfigKey("tudou")));
|
||||
// 测试 type 不匹配
|
||||
configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType())));
|
||||
// 测试 createTime 不匹配
|
||||
@@ -230,7 +230,7 @@ public class ConfigServiceTest extends BaseDbUnitTest {
|
||||
ConfigDO dbConfig = randomConfigDO();
|
||||
configMapper.insert(dbConfig);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
String key = dbConfig.getKey();
|
||||
String key = dbConfig.getConfigKey();
|
||||
|
||||
// 调用
|
||||
ConfigDO config = configService.getConfigByKey(key);
|
||||
|
@@ -0,0 +1,123 @@
|
||||
package cn.iocoder.yudao.module.infra.service.db;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import org.jasypt.encryption.StringEncryptor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* {@link DataSourceConfigServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(DataSourceConfigServiceImpl.class)
|
||||
public class DataSourceConfigServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private DataSourceConfigServiceImpl dataSourceConfigService;
|
||||
|
||||
@Resource
|
||||
private DataSourceConfigMapper dataSourceConfigMapper;
|
||||
|
||||
@MockBean
|
||||
private StringEncryptor stringEncryptor;
|
||||
|
||||
@MockBean
|
||||
private DynamicDataSourceProperties dynamicDataSourceProperties;
|
||||
|
||||
@Test
|
||||
public void testCreateDataSourceConfig_success() {
|
||||
try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) {
|
||||
// 准备参数
|
||||
DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class);
|
||||
// mock 方法
|
||||
when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
|
||||
databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()),
|
||||
eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true);
|
||||
|
||||
// 调用
|
||||
Long dataSourceConfigId = dataSourceConfigService.createDataSourceConfig(reqVO);
|
||||
// 断言
|
||||
assertNotNull(dataSourceConfigId);
|
||||
// 校验记录的属性是否正确
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(dataSourceConfigId);
|
||||
assertPojoEquals(reqVO, dataSourceConfig, "password");
|
||||
assertEquals("123456", dataSourceConfig.getPassword());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateDataSourceConfig_success() {
|
||||
try (MockedStatic<JdbcUtils> databaseUtilsMock = mockStatic(JdbcUtils.class)) {
|
||||
// mock 数据
|
||||
DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class);
|
||||
dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
DataSourceConfigUpdateReqVO reqVO = randomPojo(DataSourceConfigUpdateReqVO.class, o -> {
|
||||
o.setId(dbDataSourceConfig.getId()); // 设置更新的 ID
|
||||
});
|
||||
// mock 方法
|
||||
when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456");
|
||||
databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()),
|
||||
eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true);
|
||||
|
||||
// 调用
|
||||
dataSourceConfigService.updateDataSourceConfig(reqVO);
|
||||
// 校验是否更新正确
|
||||
DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, dataSourceConfig, "password");
|
||||
assertEquals("123456", dataSourceConfig.getPassword());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateDataSourceConfig_notExists() {
|
||||
// 准备参数
|
||||
DataSourceConfigUpdateReqVO reqVO = randomPojo(DataSourceConfigUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> dataSourceConfigService.updateDataSourceConfig(reqVO), DATA_SOURCE_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteDataSourceConfig_success() {
|
||||
// mock 数据
|
||||
DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class);
|
||||
dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbDataSourceConfig.getId();
|
||||
|
||||
// 调用
|
||||
dataSourceConfigService.deleteDataSourceConfig(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(dataSourceConfigMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteDataSourceConfig_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> dataSourceConfigService.deleteDataSourceConfig(id), DATA_SOURCE_CONFIG_NOT_EXISTS);
|
||||
}
|
||||
|
||||
}
|
@@ -9,3 +9,4 @@ DELETE FROM "infra_file";
|
||||
DELETE FROM "infra_api_error_log";
|
||||
DELETE FROM "infra_test_demo";
|
||||
DELETE FROM "infra_file_config";
|
||||
DELETE FROM "infra_data_source_config";
|
||||
|
@@ -168,3 +168,17 @@ CREATE TABLE IF NOT EXISTS "infra_test_demo" (
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '字典类型表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "infra_data_source_config" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"url" varchar(1024) NOT NULL,
|
||||
"username" varchar(255) NOT NULL,
|
||||
"password" varchar(255) NOT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar(64) DEFAULT '',
|
||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '数据源配置表';
|
||||
|
Reference in New Issue
Block a user