适配 Oracle 数据库

1. 适配表名是大写的情况
2. 优化代码生成器的校验逻辑
This commit is contained in:
YunaiV 2022-05-01 19:47:30 +08:00
parent 6f18adb54a
commit 2bd2313434
6 changed files with 54 additions and 33 deletions

View File

@ -40,6 +40,8 @@ public interface ErrorCodeConstants {
ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1003001005, "字段义不存在"); ErrorCode CODEGEN_COLUMN_NOT_EXISTS = new ErrorCode(1003001005, "字段义不存在");
ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1003001006, "同步的字段不存在"); ErrorCode CODEGEN_SYNC_COLUMNS_NULL = new ErrorCode(1003001006, "同步的字段不存在");
ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1003001007, "同步失败,不存在改变"); ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1003001007, "同步失败,不存在改变");
ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1003001008, "数据库的表注释未填写");
ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1003001009, "数据库的表字段({})注释未填写");
// ========== 字典类型测试1001005000 ========== // ========== 字典类型测试1001005000 ==========
ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1001005000, "测试示例不存在"); ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1001005000, "测试示例不存在");

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.infra.service.codegen; package cn.iocoder.yudao.module.infra.service.codegen;
import cn.hutool.core.collection.CollUtil; 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.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 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.CodegenCreateListReqVO;
@ -74,12 +75,7 @@ public class CodegenServiceImpl implements CodegenService {
private Long createCodegen0(Long userId, Long dataSourceConfigId, TableInfo tableInfo) { private Long createCodegen0(Long userId, Long dataSourceConfigId, TableInfo tableInfo) {
// 校验导入的表和字段非空 // 校验导入的表和字段非空
if (tableInfo == null) { checkTableInfo(tableInfo);
throw exception(CODEGEN_IMPORT_TABLE_NULL);
}
if (CollUtil.isEmpty(tableInfo.getFields())) {
throw exception(CODEGEN_IMPORT_COLUMNS_NULL);
}
// 校验是否已经存在 // 校验是否已经存在
if (codegenTableMapper.selectByTableNameAndDataSourceConfigId(tableInfo.getName(), if (codegenTableMapper.selectByTableNameAndDataSourceConfigId(tableInfo.getName(),
dataSourceConfigId) != null) { dataSourceConfigId) != null) {
@ -92,12 +88,34 @@ public class CodegenServiceImpl implements CodegenService {
table.setScene(CodegenSceneEnum.ADMIN.getScene()); // 默认配置下使用管理后台的模板 table.setScene(CodegenSceneEnum.ADMIN.getScene()); // 默认配置下使用管理后台的模板
table.setAuthor(userApi.getUser(userId).getNickname()); table.setAuthor(userApi.getUser(userId).getNickname());
codegenTableMapper.insert(table); codegenTableMapper.insert(table);
// 构建 CodegenColumnDO 数组插入到 DB // 构建 CodegenColumnDO 数组插入到 DB
List<CodegenColumnDO> columns = codegenBuilder.buildColumns(table.getId(), tableInfo.getFields()); List<CodegenColumnDO> columns = codegenBuilder.buildColumns(table.getId(), tableInfo.getFields());
// 如果没有主键则使用第一个字段作为主键
if (!tableInfo.isHavePrimaryKey()) {
columns.get(0).setPrimaryKey(true);
}
codegenColumnMapper.insertBatch(columns); codegenColumnMapper.insertBatch(columns);
return table.getId(); return table.getId();
} }
private void checkTableInfo(TableInfo tableInfo) {
if (tableInfo == null) {
throw exception(CODEGEN_IMPORT_TABLE_NULL);
}
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 @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateCodegen(CodegenUpdateReqVO updateReqVO) { public void updateCodegen(CodegenUpdateReqVO updateReqVO) {
@ -129,12 +147,9 @@ public class CodegenServiceImpl implements CodegenService {
} }
private void syncCodegen0(Long tableId, TableInfo tableInfo) { private void syncCodegen0(Long tableId, TableInfo tableInfo) {
// 校验导入的字段不为空 // 校验导入的表和字段非空
checkTableInfo(tableInfo);
List<TableField> tableFields = tableInfo.getFields(); List<TableField> tableFields = tableInfo.getFields();
if (CollUtil.isEmpty(tableFields)) {
throw exception(CODEGEN_SYNC_COLUMNS_NULL);
}
Set<String> tableFieldNames = CollectionUtils.convertSet(tableFields, TableField::getName);
// 构建 CodegenColumnDO 数组只同步新增的字段 // 构建 CodegenColumnDO 数组只同步新增的字段
List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId); List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId);
@ -142,6 +157,7 @@ public class CodegenServiceImpl implements CodegenService {
// 移除已经存在的字段 // 移除已经存在的字段
tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName())); tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName()));
// 计算需要删除的字段 // 计算需要删除的字段
Set<String> tableFieldNames = CollectionUtils.convertSet(tableFields, TableField::getName);
Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !tableFieldNames.contains(column.getColumnName())) Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !tableFieldNames.contains(column.getColumnName()))
.map(CodegenColumnDO::getId).collect(Collectors.toSet()); .map(CodegenColumnDO::getId).collect(Collectors.toSet());
if (CollUtil.isEmpty(tableFields) && CollUtil.isEmpty(deleteColumnIds)) { if (CollUtil.isEmpty(tableFields) && CollUtil.isEmpty(deleteColumnIds)) {
@ -206,9 +222,9 @@ public class CodegenServiceImpl implements CodegenService {
public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) {
List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment);
// 移除置顶前缀的表名 // TODO 未来做成可配置 // 移除置顶前缀的表名 // TODO 未来做成可配置
tables.removeIf(table -> table.getName().startsWith("QRTZ_")); tables.removeIf(table -> table.getName().toUpperCase().startsWith("QRTZ_"));
tables.removeIf(table -> table.getName().startsWith("ACT_")); tables.removeIf(table -> table.getName().toUpperCase().startsWith("ACT_"));
tables.removeIf(table -> table.getName().startsWith("FLW_")); tables.removeIf(table -> table.getName().toUpperCase().startsWith("FLW_"));
// 移除已经生成的表 // 移除已经生成的表
// 移除在 Codegen 已经存在的 // 移除在 Codegen 已经存在的
Set<String> existsTables = CollectionUtils.convertSet( Set<String> existsTables = CollectionUtils.convertSet(

View File

@ -105,15 +105,17 @@ public class CodegenBuilder {
* @param table 表定义 * @param table 表定义
*/ */
private void initTableDefault(CodegenTableDO table) { private void initTableDefault(CodegenTableDO table) {
// system_dept 举例子moduleName systembusinessName deptclassName SystemDept // system_dept 举例子moduleName systembusinessName deptclassName Dept
// 如果不希望 System 前缀则可以手动在代码生成 - 修改生成配置 - 基本信息将实体类名称改为 Dept 即可 // 如果希望以 System 前缀则可以手动在代码生成 - 修改生成配置 - 基本信息将实体类名称改为 SystemDept 即可
table.setModuleName(subBefore(table.getTableName(), '_', false)); // 第一个 _ 前缀的前面作为 module 名字 String tableName = table.getTableName().toLowerCase();
table.setBusinessName(toCamelCase(subAfter(table.getTableName(), // 第一步_ 前缀的前面作为 module 名字第二步moduleName 必须小写
'_', false))); // 第一步第一个 _ 前缀的后面作为 module 名字; 第二步可能存在多个 _ 的情况转换成驼峰 table.setModuleName(subBefore(tableName, '_', false).toLowerCase());
table.setClassName(upperFirst(toCamelCase( // 驼峰 + 首字母大写 // 第一步第一个 _ 前缀的后面作为 module 名字; 第二步可能存在多个 _ 的情况转换成驼峰; 第三步businessName 必须小写
subAfter(table.getTableName(), '_', false)))); // 第一个 _ 前缀的前面作为 class 名字 table.setBusinessName(toCamelCase(subAfter(tableName, '_', false)).toLowerCase());
table.setClassComment(subBefore(table.getTableComment(), // 去除结尾的表作为类描述 // 驼峰 + 首字母大写第一步第一个 _ 前缀的后面作为 class 名字第二步驼峰命名
'表', true)); table.setClassName(upperFirst(toCamelCase(subAfter(tableName, '_', false))));
// 去除结尾的表作为类描述
table.setClassComment(StrUtil.removeSuffixIgnoreCase(table.getTableComment(), ""));
table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType());
} }

View File

@ -10,7 +10,8 @@ import ${BaseDOClassName};
* *
* @author ${table.author} * @author ${table.author}
*/ */
@TableName("${table.tableName}") @TableName("${table.tableName.toLowerCase()}")
@KeySequence("${table.tableName.toLowerCase()}_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)

View File

@ -1,5 +1,5 @@
-- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tables.sql 文件里 -- 将该建表 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) #foreach ($column in $columns)
#if (${column.javaType} == 'Long') #if (${column.javaType} == 'Long')
#set ($dataType='bigint') #set ($dataType='bigint')
@ -24,11 +24,11 @@ CREATE TABLE IF NOT EXISTS "${table.tableName}" (
#elseif (${column.columnName} == 'deleted') #elseif (${column.columnName} == 'deleted')
"deleted" bit NOT NULL DEFAULT FALSE, "deleted" bit NOT NULL DEFAULT FALSE,
#else #else
"${column.columnName}" ${dataType}#if (${column.nullable} == false) NOT NULL#end, "${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end,
#end #end
#end #end
#end #end
PRIMARY KEY ("${primaryColumn.columnName}") PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}")
) COMMENT '${table.tableComment}'; ) COMMENT '${table.tableComment}';
-- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里 -- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里

View File

@ -1,7 +1,7 @@
-- 菜单 SQL -- 菜单 SQL
INSERT INTO `system_menu`( INSERT INTO system_menu(
`name`, `permission`, `menu_type`, `sort`, `parent_id`, name, permission, type, sort, parent_id,
`path`, `icon`, `component`, `status` path, icon, component, status
) )
VALUES ( VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId}, '${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
@ -16,9 +16,9 @@ SELECT @parentId := LAST_INSERT_ID();
#set ($functionOps = ['query', 'create', 'update', 'delete', 'export']) #set ($functionOps = ['query', 'create', 'update', 'delete', 'export'])
#foreach ($functionName in $functionNames) #foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1) #set ($index = $foreach.count - 1)
INSERT INTO `system_menu`( INSERT INTO system_menu(
`name`, `permission`, `menu_type`, `sort`, `parent_id`, name, permission, type, sort, parent_id,
`path`, `icon`, `component`, `status` path, icon, component, status
) )
VALUES ( VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId, '${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,