diff --git a/pom.xml b/pom.xml
index dd9fbe7d0..d93101c89 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,7 @@
1.4.1.Final
5.5.6
2.2.7
+ 2.2
@@ -221,6 +222,12 @@
${easyexcel.verion}
+
+ org.apache.velocity
+ velocity-engine-core
+ ${velocity.version}
+
+
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictTypeDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictTypeDO.java
index e9816a5bd..bb663d182 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictTypeDO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dict/SysDictTypeDO.java
@@ -5,8 +5,7 @@ import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
+import lombok.*;
/**
* 字典类型表
@@ -16,6 +15,10 @@ import lombok.EqualsAndHashCode;
@TableName("sys_dict_type")
@Data
@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
public class SysDictTypeDO extends BaseDO {
/**
diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java
index 9e88678f4..ee570ba4f 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolCodegenColumnMapper.java
@@ -2,8 +2,18 @@ package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen;
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
+import java.util.List;
+
@Mapper
public interface ToolCodegenColumnMapper extends BaseMapperX {
+
+ default List selectByTableId(Long tableId) {
+ return selectList(new QueryWrapper()
+ .eq("table_id", tableId)
+ .orderByAsc("ordinal_position"));
+ }
+
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolCodegenColumnDO.java b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolCodegenColumnDO.java
index cebb37343..4cc7e9a33 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolCodegenColumnDO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolCodegenColumnDO.java
@@ -95,16 +95,19 @@ public class ToolCodegenColumnDO extends BaseDO {
*/
private Boolean updateOperation;
/**
- * 是否为 List 查询操作的返回字段
+ * 是否为 List 查询操作的字段
*/
- private Boolean listOperationResult;
+ private Boolean listOperation;
/**
* List 查询操作的条件类型
- * 如果为空,则说明不是查询字段
*
* 枚举 {@link ToolCodegenColumnListConditionEnum}
*/
private String listOperationCondition;
+ /**
+ * 是否为 List 查询操作的返回字段
+ */
+ private Boolean listOperationResult;
// ========== UI 相关字段 ==========
diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java
new file mode 100644
index 000000000..8e89e4e8c
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java
@@ -0,0 +1,44 @@
+package cn.iocoder.dashboard.modules.tool.service.codegen.impl;
+
+import cn.hutool.extra.template.TemplateConfig;
+import cn.hutool.extra.template.TemplateEngine;
+import cn.hutool.extra.template.TemplateUtil;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 代码生成的引擎,用于具体生成代码
+ * 目前基于 {@link org.apache.velocity.app.Velocity} 模板引擎实现
+ *
+ * 考虑到 Java 模板引擎的框架非常多,Freemarker、Velocity、Thymeleaf 等等,所以我们采用 hutool 封装的 {@link cn.hutool.extra.template.Template} 抽象
+ *
+ * @author 芋道源码
+ */
+@Component
+public class ToolCodegenEngine {
+
+ /**
+ * 模板引擎,由 hutool 实现
+ */
+ private final TemplateEngine templateEngine;
+
+ public ToolCodegenEngine() {
+ TemplateConfig config = new TemplateConfig();
+ config.setResourceMode(TemplateConfig.ResourceMode.CLASSPATH);
+ this.templateEngine = TemplateUtil.createEngine(config);
+ }
+
+ public void execute(ToolCodegenTableDO table, List columns) {
+ Map bindingMap = new HashMap<>();
+ bindingMap.put("table", table);
+ bindingMap.put("columns", columns);
+ String result = templateEngine.getTemplate("codegen/dal/do.vm").render(bindingMap);
+ System.out.println(result);
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java
index d1094539d..d8b5b2421 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java
@@ -5,16 +5,9 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.modules.tool.convert.codegen.CodegenConvert;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenColumnMapper;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenTableMapper;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaColumnMapper;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolInformationSchemaTableMapper;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO;
-import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO;
-import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnHtmlTypeEnum;
-import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodegenColumnListConditionEnum;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.*;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.*;
+import cn.iocoder.dashboard.modules.tool.enums.codegen.*;
import cn.iocoder.dashboard.modules.tool.service.codegen.ToolCodegenService;
import com.google.common.collect.Sets;
import org.springframework.stereotype.Service;
@@ -60,8 +53,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
/**
* 新增操作,不需要传递的字段
*/
- private static final Set CREATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet(
- "id");
+ private static final Set CREATE_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet("id");
/**
* 修改操作,不需要传递的字段
*/
@@ -69,11 +61,11 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
/**
* 列表操作的条件,不需要传递的字段
*/
- private static final Set LIST_OPERATION_CONDITION_COLUMN = Sets.newHashSet();
+ private static final Set LIST_OPERATION_EXCLUDE_COLUMN = Sets.newHashSet("id");
/**
* 列表操作的结果,不需要返回的字段
*/
- private static final Set LIST_OPERATION_RESULT_COLUMN = Sets.newHashSet();
+ private static final Set LIST_OPERATION_RESULT_EXCLUDE_COLUMN = Sets.newHashSet();
/**
* Java 类型与 MySQL 类型的映射关系
@@ -90,13 +82,15 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
.build();
static {
+ // 处理 OPERATION 相关的字段
Arrays.stream(BaseDO.class.getDeclaredFields()).forEach(field -> {
CREATE_OPERATION_EXCLUDE_COLUMN.add(field.getName());
UPDATE_OPERATION_EXCLUDE_COLUMN.add(field.getName());
- LIST_OPERATION_CONDITION_COLUMN.add(field.getName());
- LIST_OPERATION_RESULT_COLUMN.add(field.getName());
+ LIST_OPERATION_EXCLUDE_COLUMN.add(field.getName());
+ LIST_OPERATION_RESULT_EXCLUDE_COLUMN.add(field.getName());
});
- LIST_OPERATION_RESULT_COLUMN.remove("create_time"); // 创建时间,还是需要返回的
+ LIST_OPERATION_EXCLUDE_COLUMN.remove("create_time"); // 创建时间,还是可能需要传递的
+ LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("create_time"); // 创建时间,还是需要返回的
}
@Resource
@@ -134,7 +128,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
columns.forEach(column -> {
initColumnDefault(column);
column.setTableId(table.getId());
- codegenColumnMapper.insert(column);
+ codegenColumnMapper.insert(column); // TODO 批量插入
});
return table.getId();
}
@@ -150,10 +144,11 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
table.setBusinessName(StrUtil.subAfter(table.getTableName(),
'_', false)); // 第一个 _ 前缀的后面,作为 module 名字
table.setBusinessName(StrUtil.toCamelCase(table.getBusinessName())); // 可能存在多个 _ 的情况,转换成驼峰
- table.setClassName(StrUtil.toCamelCase(table.getClassName())); // 驼峰
- table.setClassComment(StrUtil.subBefore(table.getClassComment(), // 去除结尾的表,作为类描述
+ table.setClassName(StrUtil.upperFirst(StrUtil.toCamelCase(table.getTableName()))); // 驼峰 + 首字母大写
+ table.setClassComment(StrUtil.subBefore(table.getTableComment(), // 去除结尾的表,作为类描述
'表', true));
table.setAuthor("芋艿"); // TODO 稍后改成创建人
+ table.setTemplateType(ToolCodegenTemplateTypeEnum.CRUD.getType());
}
/**
@@ -175,7 +170,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
column.setJavaField(StrUtil.toCamelCase(column.getColumnName()));
// 处理 dictType 字段,暂无
// 处理 javaType 字段
- String dbType = StrUtil.subBefore(column.getColumnName(), ')', false);
+ String dbType = StrUtil.subBefore(column.getColumnType(), '(', false);
javaTypeMappings.entrySet().stream()
.filter(entry -> entry.getValue().contains(dbType))
.findFirst().ifPresent(entry -> column.setJavaType(entry.getKey()));
@@ -187,26 +182,29 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
private void processColumnOperation(ToolCodegenColumnDO column) {
// 处理 createOperation 字段
- column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName())
- && !column.getPrimaryKey()); // 非主键
+ column.setCreateOperation(!CREATE_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField())
+ && !column.getPrimaryKey()); // 对于主键,创建时无需传递
// 处理 updateOperation 字段
- column.setUpdateOperation(!UPDATE_OPERATION_EXCLUDE_COLUMN.contains(column.getColumnName()));
- // 处理 listOperationResult 字段
- column.setListOperationResult(!LIST_OPERATION_RESULT_COLUMN.contains(column.getColumnName()));
- // 处理 listOperationCondition 字段。默认设置为需要过滤的条件,手动进行取消
- if (!LIST_OPERATION_CONDITION_COLUMN.contains(column.getColumnName())
- && !column.getPrimaryKey()) { // 非主键
+ column.setUpdateOperation(!UPDATE_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField())
+ || column.getPrimaryKey()); // 对于主键,更新时需要传递
+ // 处理 listOperation 字段
+ column.setListOperation(!LIST_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField())
+ && !column.getPrimaryKey()); // 对于主键,列表过滤不需要传递
+ // 处理 listOperationCondition 字段
+ columnListOperationConditionMappings.entrySet().stream()
+ .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey()))
+ .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition()));
+ if (column.getListOperationCondition() == null) {
column.setListOperationCondition(ToolCodegenColumnListConditionEnum.EQ.getCondition());
}
- columnListOperationConditionMappings.entrySet().stream()
- .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey()))
- .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition()));
+ // 处理 listOperationResult 字段
+ column.setListOperationResult(!LIST_OPERATION_RESULT_EXCLUDE_COLUMN.contains(column.getJavaField()));
}
private void processColumnUI(ToolCodegenColumnDO column) {
// 基于后缀进行匹配
columnHtmlTypeMappings.entrySet().stream()
- .filter(entry -> StrUtil.endWithIgnoreCase(column.getColumnName(), entry.getKey()))
+ .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey()))
.findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType()));
// 如果是 Boolean 类型时,设置为 radio 类型.
// 其它类型,因为字段名可以相对保障,所以不进行处理。例如说 date 对应 datetime 类型.
diff --git a/src/main/resources/codegen/dal/do.vm b/src/main/resources/codegen/dal/do.vm
new file mode 100644
index 000000000..0e5db0e7b
--- /dev/null
+++ b/src/main/resources/codegen/dal/do.vm
@@ -0,0 +1,30 @@
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.*;
+import java.util.*;
+
+/**
+* ${table.description}
+*/
+@TableName("${table.tableName}")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ${table.tableName}DO extends BaseDO {
+
+#foreach ($column in $columns)
+ /**
+ * ${column.columnComment}
+ */
+#if(${column.primaryKey} && ${column.javaType} != 'String')
+ @TableId
+#end
+#if(${column.primaryKey} && ${column.javaType} == 'String')
+ @TableId(type = IdType.INPUT)
+#end
+ private ${column.javaType} ${column.javaField};
+#end
+
+}
diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java
new file mode 100644
index 000000000..faf4d850b
--- /dev/null
+++ b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java
@@ -0,0 +1,32 @@
+package cn.iocoder.dashboard.modules.tool.service.codegen.impl;
+
+import cn.iocoder.dashboard.TestApplication;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenColumnMapper;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen.ToolCodegenTableMapper;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenColumnDO;
+import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolCodegenTableDO;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class ToolCodegenEngineTest {
+
+ @Resource
+ private ToolCodegenTableMapper codegenTableMapper;
+ @Resource
+ private ToolCodegenColumnMapper codegenColumnMapper;
+
+ @Resource
+ private ToolCodegenEngine codegenEngine;
+
+ @Test
+ public void testExecute() {
+ ToolCodegenTableDO table = codegenTableMapper.selectById(8);
+ List columns = codegenColumnMapper.selectByTableId(table.getId());
+ codegenEngine.execute(table, columns);
+ }
+
+}
diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java
new file mode 100644
index 000000000..f534e9769
--- /dev/null
+++ b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java
@@ -0,0 +1,22 @@
+package cn.iocoder.dashboard.modules.tool.service.codegen.impl;
+
+import cn.iocoder.dashboard.TestApplication;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+class ToolCodegenServiceImplTest {
+
+ @Resource
+ private ToolCodegenServiceImpl toolCodegenService;
+
+ @Test
+ public void tetCreateCodegenTable() {
+ toolCodegenService.createCodegenTable("sys_dict_type");
+ }
+
+}