可以连表生成文件,但是不正确
This commit is contained in:
111
.qoder/rules/project_rules.md
Normal file
111
.qoder/rules/project_rules.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
trigger: always_on
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# 核心指令
|
||||
作为自主项目开发AI,你需要以CTO思维完整执行以下生命周期:
|
||||
1. 需求分析 → 2. 架构设计 → 3. 智能编码 → 4. 异常处理 → 5. 测试验证 → 6. 报告生成
|
||||
|
||||
# 执行规范
|
||||
1. **思维记录机制**
|
||||
- 在 `/project_logs/` 下建立按时间戳命名的Markdown文件(例:`YYYYMMDD_HHMMSS_phase.md`)
|
||||
- 每个决策节点记录:
|
||||
```markdown
|
||||
## [阶段] 项目里程碑
|
||||
- 思考路径:[列出考虑的因素和决策树]
|
||||
- 方案对比:
|
||||
│─ 选项A
|
||||
│ ├─ 优势
|
||||
│ └─ 风险
|
||||
└─ 选项B...
|
||||
- 最终选择:附带可验证的决策依据
|
||||
```
|
||||
|
||||
2. **自主开发协议**
|
||||
- 采用「OODA循环」模式:
|
||||
```python
|
||||
while not project_success:
|
||||
observe(requirements)
|
||||
orient(design_patterns)
|
||||
decide(optimal_solution)
|
||||
act(implement_and_test)
|
||||
```
|
||||
|
||||
3. **异常处理矩阵**
|
||||
- 建立 `/error_handling/` 知识库,分类处理:
|
||||
│─ 逻辑错误 → 启用约束求解器
|
||||
│─ 运行时异常 → 触发沙盒调试
|
||||
└─ 系统依赖问题 → 自动环境检测
|
||||
└─ 解决思考记录 → 后续异常参考
|
||||
|
||||
# 阶段详解
|
||||
|
||||
1. **需求拆解阶段**
|
||||
- 输入:原始需求文档
|
||||
- 输出:
|
||||
- 功能点AST抽象语法树
|
||||
- 非功能性需求矩阵(性能/安全/扩展性)
|
||||
|
||||
2. **架构设计阶段**
|
||||
- 生成:
|
||||
- 模块依赖图(PlantUML格式)
|
||||
- 技术选型决策表(含权重评分)
|
||||
|
||||
3. **智能编码阶段**
|
||||
- 实现:
|
||||
- 自修正代码(嵌入式TODO标注)
|
||||
- 自动生成单元测试桩
|
||||
|
||||
4. **测试套件**
|
||||
- 实施三层验证:
|
||||
1. 静态分析(AST遍历检查)
|
||||
2. 动态模糊测试
|
||||
3. 场景覆盖率检测
|
||||
|
||||
5. **报告生成**
|
||||
- 输出三维度报告:
|
||||
```latex
|
||||
\section{质量指标}
|
||||
- 代码熵值:≤0.3
|
||||
- 分支覆盖率:≥85%
|
||||
\section{待优化项}
|
||||
- 内存泄露风险点定位
|
||||
```
|
||||
|
||||
# 持久化要求
|
||||
1. 版本化管理所有产物:
|
||||
```
|
||||
/project_artifacts/
|
||||
├─ design/
|
||||
│ └─ architecture_decision_record.md
|
||||
├─ src/
|
||||
│ └─ self_documenting_code.py
|
||||
└─ tests/
|
||||
├─ fuzz_test_cases.json
|
||||
└─ coverage_visualization.html
|
||||
```
|
||||
|
||||
2. 建立跨阶段索引文件:
|
||||
```yaml
|
||||
project_metadata:
|
||||
timeline:
|
||||
- phase: requirements_analysis
|
||||
timestamp: ISO8601
|
||||
decision_hash: SHA256
|
||||
dependency_graph: neo4j_export.json
|
||||
```
|
||||
|
||||
# 异常恢复协议
|
||||
当检测到阻塞性问题时:
|
||||
1. 自动生成最小可复现用例
|
||||
2. 隔离到 `/quarantine/` 目录
|
||||
3. 激活备选方案评估流程(蒙特卡洛模拟)
|
||||
|
||||
# 优化反馈循环
|
||||
在每次迭代后:
|
||||
- 用强化学习调整自身prompt权重
|
||||
- 更新 `/knowledge_base/` 中的模式库
|
||||
- 生成改进路线图(含时间预估)
|
||||
|
||||
请确认理解上述框架,并以结构化JSON格式输出首个决策检查点。
|
||||
24
.qoder/rules/user_rules.md
Normal file
24
.qoder/rules/user_rules.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
trigger: always_on
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
严格遵循阿里巴巴Java开发规范,包括但不限于:
|
||||
- 命名规范
|
||||
- 代码格式
|
||||
- 注释规范
|
||||
- 异常处理规范
|
||||
- 数据库操作规范
|
||||
- 缓存操作规范
|
||||
- 日志记录规范
|
||||
- 性能优化规范
|
||||
|
||||
严格遵守JavaScript,Html,Css规范,包括但不限于:
|
||||
- 命名规范
|
||||
- 代码格式
|
||||
- 注释规范
|
||||
- 异常处理规范
|
||||
- 数据库操作规范
|
||||
- 缓存操作规范
|
||||
- 日志记录规范
|
||||
- 性能优化规范
|
||||
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "interactive",
|
||||
"java.compile.nullAnalysis.mode": "automatic"
|
||||
}
|
||||
@@ -103,6 +103,25 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.40</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<mainClass>example.Db2JavaExample</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -5,7 +5,11 @@ import com.yexuejc.db2java.core.enums.TemplateEngine;
|
||||
import com.yexuejc.db2java.core.generator.*;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineFactory;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineProcessor;
|
||||
import com.yexuejc.db2java.core.utils.DatabaseUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -15,8 +19,38 @@ import java.util.List;
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
@Slf4j
|
||||
public class Db2JavaCore {
|
||||
|
||||
/**
|
||||
* 根据配置生成代码的主方法
|
||||
*
|
||||
* @param config 生成配置
|
||||
* @return 生成结果
|
||||
* @throws Exception 生成异常
|
||||
*/
|
||||
public static GenerationResult generate(GenerationConfig config) throws Exception {
|
||||
// 建立数据库连接
|
||||
Connection connection = DriverManager.getConnection(
|
||||
config.getUrl(),
|
||||
config.getUsername(),
|
||||
config.getPassword()
|
||||
);
|
||||
|
||||
try {
|
||||
// 获取表信息
|
||||
List<TableInfo> tableInfos = DatabaseUtils.getTableInfos(connection, config);
|
||||
System.out.println("获取表信息成功,共有" + tableInfos.size() + "张表");
|
||||
System.out.println("开始调用引擎生成代码");
|
||||
// 调用原有的generateCode方法
|
||||
return generateCode(tableInfos, config);
|
||||
} finally {
|
||||
if (connection != null && !connection.isClosed()) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码的主方法
|
||||
*
|
||||
@@ -27,21 +61,27 @@ public class Db2JavaCore {
|
||||
*/
|
||||
public static GenerationResult generateCode(List<TableInfo> tableInfos, GenerationConfig config) throws Exception {
|
||||
// 验证配置
|
||||
System.out.println("验证生成配置");
|
||||
validateConfig(config);
|
||||
|
||||
// 获取代码生成器
|
||||
System.out.println("获取代码生成器");
|
||||
CodeGenerator codeGenerator = CodeGeneratorFactory.getGenerator(config.getMode());
|
||||
|
||||
// 获取模板引擎处理器
|
||||
System.out.println("获取模板引擎处理器");
|
||||
TemplateEngineProcessor templateProcessor = TemplateEngineFactory.getProcessor(config.getEngine());
|
||||
|
||||
// 初始化生成器
|
||||
System.out.println("初始化代码生成器");
|
||||
codeGenerator.initialize(config);
|
||||
|
||||
// 初始化模板引擎
|
||||
System.out.println("初始化模板引擎处理器");
|
||||
templateProcessor.initialize(null);
|
||||
|
||||
// 执行代码生成
|
||||
System.out.println("开始执行代码生成");
|
||||
return codeGenerator.generate(tableInfos, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,31 @@ public class FieldInfo {
|
||||
*/
|
||||
private Integer scale;
|
||||
|
||||
/**
|
||||
* 数据类型代码
|
||||
*/
|
||||
private int dataType;
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 字段在表中的位置
|
||||
*/
|
||||
private int ordinalPosition;
|
||||
|
||||
/**
|
||||
* 小数位数
|
||||
*/
|
||||
private int decimalDigits;
|
||||
|
||||
/**
|
||||
* 字段大小
|
||||
*/
|
||||
private int columnSize;
|
||||
|
||||
public FieldInfo() {
|
||||
}
|
||||
|
||||
@@ -135,4 +160,44 @@ public class FieldInfo {
|
||||
public void setScale(Integer scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public int getDataType() {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
public void setDataType(int dataType) {
|
||||
this.dataType = dataType;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(String defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public int getOrdinalPosition() {
|
||||
return ordinalPosition;
|
||||
}
|
||||
|
||||
public void setOrdinalPosition(int ordinalPosition) {
|
||||
this.ordinalPosition = ordinalPosition;
|
||||
}
|
||||
|
||||
public int getDecimalDigits() {
|
||||
return decimalDigits;
|
||||
}
|
||||
|
||||
public void setDecimalDigits(int decimalDigits) {
|
||||
this.decimalDigits = decimalDigits;
|
||||
}
|
||||
|
||||
public int getColumnSize() {
|
||||
return columnSize;
|
||||
}
|
||||
|
||||
public void setColumnSize(int columnSize) {
|
||||
this.columnSize = columnSize;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,26 @@ import java.util.Map;
|
||||
*/
|
||||
public class GenerationConfig {
|
||||
|
||||
/**
|
||||
* 数据库URL
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 数据库用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 数据库密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 数据库驱动类名
|
||||
*/
|
||||
private String driverClassName;
|
||||
|
||||
/**
|
||||
* 生成模式
|
||||
*/
|
||||
@@ -79,6 +99,38 @@ public class GenerationConfig {
|
||||
}
|
||||
|
||||
// Getter and Setter methods
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getDriverClassName() {
|
||||
return driverClassName;
|
||||
}
|
||||
|
||||
public void setDriverClassName(String driverClassName) {
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
@@ -111,6 +163,11 @@ public class GenerationConfig {
|
||||
this.outputPath = outputPath;
|
||||
}
|
||||
|
||||
// 兼容旧版本的setter方法
|
||||
public void setOutDir(String outDir) {
|
||||
this.outputPath = outDir;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.yexuejc.db2java.core.generator.*;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineFactory;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineProcessor;
|
||||
import com.yexuejc.db2java.core.utils.FileUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
@@ -15,6 +16,7 @@ import java.util.*;
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
@Slf4j
|
||||
public class HibernateCodeGenerator implements CodeGenerator {
|
||||
|
||||
@Override
|
||||
@@ -81,6 +83,7 @@ public class HibernateCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "Entity", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成Hibernate Entity失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -315,6 +318,7 @@ public class HibernateCodeGenerator implements CodeGenerator {
|
||||
generatedFile.setFileSize(FileUtils.getFileSize(generatedFile.getFilePath()));
|
||||
} catch (Exception e) {
|
||||
System.err.println("写入文件失败: " + generatedFile.getFilePath() + ", 错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.yexuejc.db2java.core.generator.*;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineFactory;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineProcessor;
|
||||
import com.yexuejc.db2java.core.utils.FileUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
@@ -15,6 +16,7 @@ import java.util.*;
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
@Slf4j
|
||||
public class JpaCodeGenerator implements CodeGenerator {
|
||||
|
||||
@Override
|
||||
@@ -81,6 +83,7 @@ public class JpaCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "Entity", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成JPA Entity失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -387,6 +390,7 @@ public class JpaCodeGenerator implements CodeGenerator {
|
||||
generatedFile.setFileSize(FileUtils.getFileSize(generatedFile.getFilePath()));
|
||||
} catch (Exception e) {
|
||||
System.err.println("写入文件失败: " + generatedFile.getFilePath() + ", 错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.yexuejc.db2java.core.generator.*;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineFactory;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineProcessor;
|
||||
import com.yexuejc.db2java.core.utils.FileUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
@@ -15,6 +16,7 @@ import java.util.*;
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
@Slf4j
|
||||
public class MybatisCodeGenerator implements CodeGenerator {
|
||||
|
||||
@Override
|
||||
@@ -189,9 +191,12 @@ public class MybatisCodeGenerator implements CodeGenerator {
|
||||
dataModel.put("entity", tableInfo.getEntityName());
|
||||
dataModel.put("table", createTableMap(tableInfo));
|
||||
|
||||
// 导入包
|
||||
dataModel.put("importEntityFrameworkPackages", getEntityImports(config.isLombok()));
|
||||
dataModel.put("importEntityJavaPackages", getJavaImports(tableInfo));
|
||||
// 导入包 - 确保顺序一致
|
||||
List<String> entityFrameworkImports = getEntityFrameworkImports(config.isLombok());
|
||||
List<String> entityJavaImports = getEntityJavaImports(tableInfo);
|
||||
|
||||
dataModel.put("importEntityFrameworkPackages", entityFrameworkImports);
|
||||
dataModel.put("importEntityJavaPackages", entityJavaImports);
|
||||
|
||||
// Lombok配置
|
||||
dataModel.put("entityLombokModel", config.isLombok());
|
||||
@@ -403,16 +408,19 @@ public class MybatisCodeGenerator implements CodeGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体类框架导入包
|
||||
* 获取实体类框架导入包 - 确保顺序一致
|
||||
*/
|
||||
private List<String> getEntityImports(boolean useLombok) {
|
||||
private List<String> getEntityFrameworkImports(boolean useLombok) {
|
||||
List<String> imports = new ArrayList<>();
|
||||
|
||||
// 添加Lombok导入
|
||||
// 添加Lombok导入(如果使用)
|
||||
if (useLombok) {
|
||||
imports.add("lombok.Data");
|
||||
}
|
||||
|
||||
// 添加序列化导入
|
||||
imports.add("java.io.Serializable");
|
||||
|
||||
// 添加关联字段需要的导入
|
||||
imports.add("java.util.List");
|
||||
|
||||
@@ -420,27 +428,25 @@ public class MybatisCodeGenerator implements CodeGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Java导入包
|
||||
* 获取Java导入包 - 确保顺序一致
|
||||
*/
|
||||
private List<String> getJavaImports(TableInfo tableInfo) {
|
||||
Set<String> imports = new HashSet<>();
|
||||
imports.add("java.io.Serializable");
|
||||
private List<String> getEntityJavaImports(TableInfo tableInfo) {
|
||||
// 使用LinkedHashSet保持顺序并去重
|
||||
Set<String> importSet = new LinkedHashSet<>();
|
||||
|
||||
// 根据字段类型添加相应的导入
|
||||
for (FieldInfo field : tableInfo.getFields()) {
|
||||
if ("LocalDateTime".equals(field.getPropertyType())) {
|
||||
imports.add("java.time.LocalDateTime");
|
||||
importSet.add("java.time.LocalDateTime");
|
||||
} else if ("LocalDate".equals(field.getPropertyType())) {
|
||||
imports.add("java.time.LocalDate");
|
||||
importSet.add("java.time.LocalDate");
|
||||
} else if ("BigDecimal".equals(field.getPropertyType())) {
|
||||
imports.add("java.math.BigDecimal");
|
||||
importSet.add("java.math.BigDecimal");
|
||||
}
|
||||
}
|
||||
|
||||
// 添加关联字段需要的导入
|
||||
imports.add("java.util.List");
|
||||
|
||||
return new ArrayList<>(imports);
|
||||
// 转换为列表并返回
|
||||
return new ArrayList<>(importSet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.yexuejc.db2java.core.generator.*;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineFactory;
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineProcessor;
|
||||
import com.yexuejc.db2java.core.utils.FileUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
@@ -15,6 +16,7 @@ import java.util.*;
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
@Slf4j
|
||||
public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
|
||||
@Override
|
||||
@@ -117,6 +119,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "Entity", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成Entity失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -135,6 +138,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "Mapper", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成Mapper失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -153,6 +157,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "Service", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成Service失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -171,6 +176,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "ServiceImpl", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成ServiceImpl失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -189,6 +195,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
return new GeneratedFile(filePath, fileName, "Controller", content);
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成Controller失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -407,8 +414,8 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
dataModel.put("superServiceImplClass", "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl");
|
||||
dataModel.put("superServiceImplClassPackage", "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl");
|
||||
dataModel.put("importServiceImplFrameworkPackages", Arrays.asList(
|
||||
"com.baomidou.mybatisplus.extension.service.impl.ServiceImpl",
|
||||
"org.springframework.stereotype.Service"
|
||||
"com.baomidou.mybatisplus.extension.service.impl.ServiceImpl",
|
||||
"org.springframework.stereotype.Service"
|
||||
));
|
||||
dataModel.put("importServiceImplJavaPackages", new ArrayList<>());
|
||||
dataModel.put("kotlin", false);
|
||||
@@ -446,9 +453,9 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
dataModel.put("superControllerClass", null); // 不继承任何类
|
||||
dataModel.put("superControllerClassPackage", null);
|
||||
dataModel.put("importControllerFrameworkPackages", Arrays.asList(
|
||||
"org.springframework.web.bind.annotation.RestController",
|
||||
"org.springframework.web.bind.annotation.RequestMapping",
|
||||
"org.springframework.beans.factory.annotation.Autowired"
|
||||
"org.springframework.web.bind.annotation.RestController",
|
||||
"org.springframework.web.bind.annotation.RequestMapping",
|
||||
"org.springframework.beans.factory.annotation.Autowired"
|
||||
));
|
||||
dataModel.put("importControllerJavaPackages", new ArrayList<>());
|
||||
dataModel.put("restControllerStyle", true);
|
||||
@@ -594,6 +601,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator {
|
||||
generatedFile.setFileSize(FileUtils.getFileSize(generatedFile.getFilePath()));
|
||||
} catch (Exception e) {
|
||||
System.err.println("写入文件失败: " + generatedFile.getFilePath() + ", 错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,29 @@
|
||||
package com.yexuejc.db2java.core.template.impl;
|
||||
|
||||
import com.yexuejc.db2java.core.template.TemplateEngineProcessor;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 改进的FreeMarker模板引擎处理器
|
||||
* 提供更完整的模板处理能力
|
||||
* Freemarker模板引擎处理器
|
||||
*
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
public class FreemarkerTemplateProcessor implements TemplateEngineProcessor {
|
||||
public class FreemarkerTemplateProcessor implements TemplateEngineProcessor {
|
||||
|
||||
private Configuration configuration;
|
||||
|
||||
@Override
|
||||
public String getEngineName() {
|
||||
return "freemarker";
|
||||
return "Freemarker";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -29,89 +33,102 @@ import java.util.Scanner;
|
||||
|
||||
@Override
|
||||
public void initialize(Map<String, Object> config) throws Exception {
|
||||
System.out.println("改进的FreeMarker引擎初始化 - 配置: " + config);
|
||||
configuration = new Configuration(Configuration.VERSION_2_3_32);
|
||||
configuration.setDefaultEncoding("UTF-8");
|
||||
configuration.setClassicCompatible(true);
|
||||
configuration.setWhitespaceStripping(false);
|
||||
|
||||
// 设置模板加载路径
|
||||
try {
|
||||
configuration.setClassForTemplateLoading(this.getClass(), "/templates");
|
||||
} catch (Exception e) {
|
||||
System.err.println("设置模板加载路径失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processTemplate(String templatePath, Map<String, Object> dataModel) throws Exception {
|
||||
// 调试输出
|
||||
System.out.println("模板路径: " + templatePath);
|
||||
// 直接根据模板路径判断生成类型,避免模板内容解析错误
|
||||
return generateFallbackContent(templatePath, dataModel);
|
||||
public String processTemplate(String templateName, Map<String, Object> dataModel) throws IOException, TemplateException {
|
||||
// 确保configuration已初始化
|
||||
if (configuration == null) {
|
||||
try {
|
||||
initialize(null);
|
||||
} catch (Exception e) {
|
||||
System.err.println("初始化Freemarker配置失败: " + e.getMessage());
|
||||
// 使用硬编码处理逻辑
|
||||
return generateCodeFromDataModel(templateName, dataModel);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试使用模板文件处理
|
||||
try {
|
||||
Template template = configuration.getTemplate(templateName);
|
||||
StringWriter writer = new StringWriter();
|
||||
template.process(dataModel, writer);
|
||||
return writer.toString();
|
||||
} catch (IOException e) {
|
||||
// 如果模板文件不存在,使用硬编码处理逻辑
|
||||
return generateCodeFromDataModel(templateName, dataModel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean templateExists(String templatePath) {
|
||||
return readTemplateFile(templatePath) != null;
|
||||
}
|
||||
// 确保configuration已初始化
|
||||
if (configuration == null) {
|
||||
try {
|
||||
initialize(null);
|
||||
} catch (Exception e) {
|
||||
System.err.println("初始化Freemarker配置失败: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取模板文件
|
||||
*/
|
||||
private String readTemplateFile(String templatePath) {
|
||||
try {
|
||||
String fullPath = "/templates/" + templatePath;
|
||||
InputStream inputStream = this.getClass().getResourceAsStream(fullPath);
|
||||
|
||||
if (inputStream == null) {
|
||||
System.err.println("模板文件不存在: " + fullPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
Scanner scanner = new Scanner(inputStream, "UTF-8");
|
||||
StringBuilder content = new StringBuilder();
|
||||
while (scanner.hasNextLine()) {
|
||||
content.append(scanner.nextLine()).append("\n");
|
||||
}
|
||||
scanner.close();
|
||||
inputStream.close();
|
||||
|
||||
return content.toString();
|
||||
configuration.getTemplate(templatePath);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
System.err.println("读取模板文件失败: " + templatePath + ", 错误: " + e.getMessage());
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 高级模板处理 - 根据模板类型生成相应的Java代码
|
||||
* 从数据模型生成代码(硬编码处理逻辑)
|
||||
*
|
||||
* @param templateName 模板名称
|
||||
* @param dataModel 数据模型
|
||||
* @return 生成的代码
|
||||
*/
|
||||
private String processAdvancedTemplate(String template, Map<String, Object> dataModel) {
|
||||
// 根据模板内容判断生成类型
|
||||
if (template.contains("@RestController") || template.contains("@Controller")) {
|
||||
return generateControllerCode(dataModel);
|
||||
} else if (template.contains("interface") && template.contains("Service")) {
|
||||
return generateServiceCode(dataModel);
|
||||
} else if (template.contains("class") && template.contains("ServiceImpl")) {
|
||||
return generateServiceImplCode(dataModel);
|
||||
} else if (template.contains("interface") && template.contains("Mapper")) {
|
||||
return generateMapperCode(dataModel);
|
||||
} else if (template.contains("<?xml") || template.contains("<mapper")) {
|
||||
private String generateCodeFromDataModel(String templateName, Map<String, Object> dataModel) {
|
||||
if (templateName.startsWith("entity")) {
|
||||
return generateEntityCode(dataModel);
|
||||
} else if (templateName.startsWith("mapper.java")) {
|
||||
return generateMapperJavaCode(dataModel);
|
||||
} else if (templateName.startsWith("mapper.xml")) {
|
||||
return generateMapperXmlCode(dataModel);
|
||||
} else {
|
||||
// 默认生成Entity代码
|
||||
return generateEntityCode(dataModel);
|
||||
// 默认处理逻辑
|
||||
return generateDefaultCode(dataModel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Entity代码
|
||||
* 生成实体类代码
|
||||
*/
|
||||
private String generateEntityCode(Map<String, Object> dataModel) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
// 获取数据
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> packageMap = (Map<String, String>) dataModel.get("package");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
String entity = safeString(dataModel.get("entity"));
|
||||
String author = safeString(dataModel.get("author"));
|
||||
String date = safeString(dataModel.get("date"));
|
||||
Boolean lombok = (Boolean) dataModel.get("entityLombokModel");
|
||||
Boolean serialVersionUID = (Boolean) dataModel.get("entitySerialVersionUID");
|
||||
Boolean entityToString = (Boolean) dataModel.get("entityToString");
|
||||
Boolean entityJpaModel = (Boolean) dataModel.get("entityJpaModel");
|
||||
Boolean entityToString = (Boolean) dataModel.get("entityToString");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
|
||||
// 包声明
|
||||
if (packageMap != null && packageMap.get("Entity") != null) {
|
||||
@@ -119,21 +136,27 @@ import java.util.Scanner;
|
||||
}
|
||||
|
||||
// 导入语句
|
||||
code.append("import java.io.Serializable;\n");
|
||||
code.append("import java.time.LocalDateTime;\n");
|
||||
code.append("import java.time.LocalDate;\n");
|
||||
code.append("import java.math.BigDecimal;\n");
|
||||
code.append("import java.util.List;\n");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> importEntityFrameworkPackages = (List<String>) dataModel.get("importEntityFrameworkPackages");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> importEntityJavaPackages = (List<String>) dataModel.get("importEntityJavaPackages");
|
||||
|
||||
// JPA导入
|
||||
if (entityJpaModel != null && entityJpaModel) {
|
||||
code.append("import javax.persistence.*;\n");
|
||||
if (importEntityFrameworkPackages != null) {
|
||||
for (String pkg : importEntityFrameworkPackages) {
|
||||
code.append("import ").append(pkg).append(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (lombok != null && lombok) {
|
||||
code.append("import lombok.Data;\n");
|
||||
if (importEntityJavaPackages != null) {
|
||||
for (String pkg : importEntityJavaPackages) {
|
||||
code.append("import ").append(pkg).append(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ((importEntityFrameworkPackages != null && !importEntityFrameworkPackages.isEmpty()) ||
|
||||
(importEntityJavaPackages != null && !importEntityJavaPackages.isEmpty())) {
|
||||
code.append("\n");
|
||||
}
|
||||
code.append("\n");
|
||||
|
||||
// 类注释
|
||||
code.append("/**\n");
|
||||
@@ -147,19 +170,17 @@ import java.util.Scanner;
|
||||
code.append(" * @since ").append(date).append("\n");
|
||||
code.append(" */\n");
|
||||
|
||||
// JPA注解
|
||||
if (entityJpaModel != null && entityJpaModel) {
|
||||
code.append("@Entity\n");
|
||||
code.append("@Table(name = \"").append(tableMap.get("name")).append("\")\n");
|
||||
// 类注解
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, String>> entityClassAnnotations = (List<Map<String, String>>) dataModel.get("entityClassAnnotations");
|
||||
if (entityClassAnnotations != null) {
|
||||
for (Map<String, String> annotation : entityClassAnnotations) {
|
||||
code.append(annotation.get("displayName")).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Lombok注解
|
||||
if (lombok != null && lombok) {
|
||||
code.append("@Data\n");
|
||||
}
|
||||
|
||||
// 类声明
|
||||
code.append("public class ").append(entity);
|
||||
// 类声明 - 使用正确的实体类名
|
||||
code.append("public class ").append(entity); // 这里使用entity变量,与文件名一致
|
||||
if (serialVersionUID != null && serialVersionUID) {
|
||||
code.append(" implements Serializable");
|
||||
}
|
||||
@@ -366,186 +387,21 @@ import java.util.Scanner;
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 备用内容生成
|
||||
*/
|
||||
private String generateFallbackContent(String templatePath, Map<String, Object> dataModel) {
|
||||
// 根据模板路径判断类型
|
||||
if (templatePath.contains("controller")) {
|
||||
return generateControllerCode(dataModel);
|
||||
} else if (templatePath.contains("service") && !templatePath.contains("serviceImpl")) {
|
||||
return generateServiceCode(dataModel);
|
||||
} else if (templatePath.contains("serviceImpl")) {
|
||||
return generateServiceImplCode(dataModel);
|
||||
} else if (templatePath.contains("mapper") && (templatePath.contains(".xml") || templatePath.endsWith("xml.ftl"))) {
|
||||
return generateMapperXmlCode(dataModel);
|
||||
} else if (templatePath.contains("mapper")) {
|
||||
return generateMapperCode(dataModel);
|
||||
} else {
|
||||
return generateEntityCode(dataModel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Controller代码
|
||||
*/
|
||||
private String generateControllerCode(Map<String, Object> dataModel) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> packageMap = (Map<String, String>) dataModel.get("package");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
String entity = safeString(dataModel.get("entity"));
|
||||
String author = safeString(dataModel.get("author"));
|
||||
String date = safeString(dataModel.get("date"));
|
||||
|
||||
// 包声明
|
||||
if (packageMap != null && packageMap.get("Controller") != null) {
|
||||
code.append("package ").append(packageMap.get("Controller")).append(";\n\n");
|
||||
}
|
||||
|
||||
// 导入语句
|
||||
code.append("import org.springframework.web.bind.annotation.RequestMapping;\n");
|
||||
code.append("import org.springframework.web.bind.annotation.RestController;\n");
|
||||
code.append("import org.springframework.beans.factory.annotation.Autowired;\n");
|
||||
if (packageMap != null) {
|
||||
code.append("import ").append(packageMap.get("Service")).append(".I").append(entity).append("Service;\n");
|
||||
}
|
||||
code.append("\n");
|
||||
|
||||
// 类注释
|
||||
code.append("/**\n");
|
||||
code.append(" * <p>\n");
|
||||
if (tableMap != null && tableMap.get("comment") != null) {
|
||||
code.append(" * ").append(tableMap.get("comment")).append(" 前端控制器\n");
|
||||
}
|
||||
code.append(" * </p>\n");
|
||||
code.append(" *\n");
|
||||
code.append(" * @author ").append(author).append("\n");
|
||||
code.append(" * @since ").append(date).append("\n");
|
||||
code.append(" */\n");
|
||||
|
||||
// 注解和类声明
|
||||
code.append("@RestController\n");
|
||||
code.append("@RequestMapping(\"/").append(entity.toLowerCase()).append("\")\n");
|
||||
code.append("public class ").append(entity).append("Controller {\n\n");
|
||||
|
||||
// 注入Service
|
||||
code.append(" @Autowired\n");
|
||||
code.append(" private I").append(entity).append("Service ").append(entity.toLowerCase()).append("Service;\n\n");
|
||||
|
||||
code.append("}\n");
|
||||
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Service接口代码
|
||||
*/
|
||||
private String generateServiceCode(Map<String, Object> dataModel) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> packageMap = (Map<String, String>) dataModel.get("package");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
String entity = safeString(dataModel.get("entity"));
|
||||
String author = safeString(dataModel.get("author"));
|
||||
String date = safeString(dataModel.get("date"));
|
||||
|
||||
// 包声明
|
||||
if (packageMap != null && packageMap.get("Service") != null) {
|
||||
code.append("package ").append(packageMap.get("Service")).append(";\n\n");
|
||||
}
|
||||
|
||||
// 导入语句
|
||||
if (packageMap != null && packageMap.get("Entity") != null) {
|
||||
code.append("import ").append(packageMap.get("Entity")).append(".").append(entity).append(";\n");
|
||||
}
|
||||
code.append("import com.baomidou.mybatisplus.extension.service.IService;\n\n");
|
||||
|
||||
// 类注释
|
||||
code.append("/**\n");
|
||||
code.append(" * <p>\n");
|
||||
if (tableMap != null && tableMap.get("comment") != null) {
|
||||
code.append(" * ").append(tableMap.get("comment")).append(" 服务类\n");
|
||||
}
|
||||
code.append(" * </p>\n");
|
||||
code.append(" *\n");
|
||||
code.append(" * @author ").append(author).append("\n");
|
||||
code.append(" * @since ").append(date).append("\n");
|
||||
code.append(" */\n");
|
||||
|
||||
// 接口声明
|
||||
code.append("public interface I").append(entity).append("Service extends IService<").append(entity).append("> {\n\n");
|
||||
code.append("}\n");
|
||||
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成ServiceImpl代码
|
||||
*/
|
||||
private String generateServiceImplCode(Map<String, Object> dataModel) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> packageMap = (Map<String, String>) dataModel.get("package");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
String entity = safeString(dataModel.get("entity"));
|
||||
String author = safeString(dataModel.get("author"));
|
||||
String date = safeString(dataModel.get("date"));
|
||||
|
||||
// 包声明
|
||||
if (packageMap != null && packageMap.get("ServiceImpl") != null) {
|
||||
code.append("package ").append(packageMap.get("ServiceImpl")).append(";\n\n");
|
||||
}
|
||||
|
||||
// 导入语句
|
||||
if (packageMap != null) {
|
||||
code.append("import ").append(packageMap.get("Entity")).append(".").append(entity).append(";\n");
|
||||
code.append("import ").append(packageMap.get("Mapper")).append(".").append(entity).append("Mapper;\n");
|
||||
code.append("import ").append(packageMap.get("Service")).append(".I").append(entity).append("Service;\n");
|
||||
}
|
||||
code.append("import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;\n");
|
||||
code.append("import org.springframework.stereotype.Service;\n\n");
|
||||
|
||||
// 类注释
|
||||
code.append("/**\n");
|
||||
code.append(" * <p>\n");
|
||||
if (tableMap != null && tableMap.get("comment") != null) {
|
||||
code.append(" * ").append(tableMap.get("comment")).append(" 服务实现类\n");
|
||||
}
|
||||
code.append(" * </p>\n");
|
||||
code.append(" *\n");
|
||||
code.append(" * @author ").append(author).append("\n");
|
||||
code.append(" * @since ").append(date).append("\n");
|
||||
code.append(" */\n");
|
||||
|
||||
// 注解和类声明
|
||||
code.append("@Service\n");
|
||||
code.append("public class ").append(entity).append("ServiceImpl extends ServiceImpl<").append(entity).append("Mapper, ").append(entity).append("> implements I").append(entity).append("Service {\n\n");
|
||||
code.append("}\n");
|
||||
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Mapper接口代码
|
||||
*/
|
||||
private String generateMapperCode(Map<String, Object> dataModel) {
|
||||
private String generateMapperJavaCode(Map<String, Object> dataModel) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> packageMap = (Map<String, String>) dataModel.get("package");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
String entity = safeString(dataModel.get("entity"));
|
||||
String author = safeString(dataModel.get("author"));
|
||||
String date = safeString(dataModel.get("date"));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> tableMap = (Map<String, Object>) dataModel.get("table");
|
||||
|
||||
// 包声明
|
||||
if (packageMap != null && packageMap.get("Mapper") != null) {
|
||||
code.append("package ").append(packageMap.get("Mapper")).append(";\n\n");
|
||||
@@ -698,6 +554,16 @@ import java.util.Scanner;
|
||||
return xml.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成默认代码
|
||||
*/
|
||||
private String generateDefaultCode(Map<String, Object> dataModel) {
|
||||
StringBuilder code = new StringBuilder();
|
||||
code.append("// 默认生成的代码\n");
|
||||
code.append("// 请检查模板文件是否存在\n");
|
||||
return code.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JDBC类型
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
package com.yexuejc.db2java.core.utils;
|
||||
|
||||
import com.yexuejc.db2java.core.generator.FieldInfo;
|
||||
import com.yexuejc.db2java.core.generator.GenerationConfig;
|
||||
import com.yexuejc.db2java.core.generator.TableInfo;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据库工具类
|
||||
* 用于获取数据库表结构信息
|
||||
*
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
public class DatabaseUtils {
|
||||
|
||||
/**
|
||||
* 获取数据库中所有表的信息
|
||||
*
|
||||
* @param connection 数据库连接
|
||||
* @param config 生成配置
|
||||
* @return 表信息列表
|
||||
* @throws SQLException SQL异常
|
||||
*/
|
||||
public static List<TableInfo> getTableInfos(Connection connection, GenerationConfig config) throws SQLException {
|
||||
List<TableInfo> tableInfos = new ArrayList<>();
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
String catalog = connection.getCatalog();
|
||||
String schemaPattern = null;
|
||||
|
||||
// 获取所有表
|
||||
try (ResultSet tables = metaData.getTables(catalog, schemaPattern, null, new String[]{"TABLE"})) {
|
||||
while (tables.next()) {
|
||||
String tableName = tables.getString("TABLE_NAME");
|
||||
|
||||
// 检查表名是否有效
|
||||
if (tableName == null || tableName.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查是否应该忽略此表
|
||||
if (shouldIgnoreTable(tableName, config)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查是否只包含特定表
|
||||
if (config.getIncludeTables() != null && config.getIncludeTables().length > 0) {
|
||||
boolean shouldInclude = false;
|
||||
for (String includeTable : config.getIncludeTables()) {
|
||||
if (includeTable.equalsIgnoreCase(tableName)) {
|
||||
shouldInclude = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shouldInclude) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
TableInfo tableInfo = getTableInfo(metaData, catalog, schemaPattern, tableName, config);
|
||||
if (tableInfo != null && tableInfo.getEntityName() != null && !tableInfo.getEntityName().trim().isEmpty()) {
|
||||
tableInfos.add(tableInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tableInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个表的信息
|
||||
*
|
||||
* @param metaData 数据库元数据
|
||||
* @param catalog 数据库目录
|
||||
* @param schemaPattern schema模式
|
||||
* @param tableName 表名
|
||||
* @param config 生成配置
|
||||
* @return 表信息
|
||||
* @throws SQLException SQL异常
|
||||
*/
|
||||
private static TableInfo getTableInfo(DatabaseMetaData metaData, String catalog, String schemaPattern, String tableName, GenerationConfig config) throws SQLException {
|
||||
// 检查表名是否有效
|
||||
if (tableName == null || tableName.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TableInfo tableInfo = new TableInfo();
|
||||
tableInfo.setTableName(tableName);
|
||||
tableInfo.setEntityName(toPascalCase(tableName)); // 表名转换为大驼峰命名
|
||||
|
||||
// 获取表注释
|
||||
try (ResultSet tableRs = metaData.getTables(catalog, schemaPattern, tableName, null)) {
|
||||
if (tableRs.next()) {
|
||||
tableInfo.setTableComment(tableRs.getString("REMARKS"));
|
||||
}
|
||||
}
|
||||
|
||||
// 获取字段信息
|
||||
List<FieldInfo> fields = new ArrayList<>();
|
||||
try (ResultSet columns = metaData.getColumns(catalog, schemaPattern, tableName, null)) {
|
||||
while (columns.next()) {
|
||||
String columnName = columns.getString("COLUMN_NAME");
|
||||
String columnType = columns.getString("TYPE_NAME");
|
||||
String remarks = columns.getString("REMARKS");
|
||||
int dataType = columns.getInt("DATA_TYPE");
|
||||
int columnSize = columns.getInt("COLUMN_SIZE");
|
||||
int decimalDigits = columns.getInt("DECIMAL_DIGITS");
|
||||
boolean isNullable = "YES".equals(columns.getString("IS_NULLABLE"));
|
||||
String columnDef = columns.getString("COLUMN_DEF");
|
||||
int ordinalPosition = columns.getInt("ORDINAL_POSITION");
|
||||
|
||||
// 检查字段名是否有效
|
||||
if (columnName == null || columnName.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FieldInfo fieldInfo = new FieldInfo();
|
||||
fieldInfo.setColumnName(columnName);
|
||||
fieldInfo.setColumnType(columnType);
|
||||
fieldInfo.setColumnComment(remarks);
|
||||
|
||||
// 根据fieldNaming配置决定属性名
|
||||
String fieldNaming = getFieldNaming(config);
|
||||
if ("camelCase".equals(fieldNaming)) {
|
||||
fieldInfo.setPropertyName(toCamelCase(columnName)); // 字段名转换为小驼峰命名
|
||||
} else {
|
||||
fieldInfo.setPropertyName(columnName);
|
||||
}
|
||||
|
||||
// 使用TypeMappingConfig进行类型映射
|
||||
fieldInfo.setPropertyType(TypeMappingConfig.getJavaType(columnType));
|
||||
|
||||
// 设置其他属性
|
||||
fieldInfo.setLength(columnSize);
|
||||
fieldInfo.setScale(decimalDigits);
|
||||
fieldInfo.setNullable(isNullable);
|
||||
|
||||
fields.add(fieldInfo);
|
||||
}
|
||||
}
|
||||
|
||||
tableInfo.setFields(fields);
|
||||
return tableInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置中获取字段命名策略
|
||||
*
|
||||
* @param config 生成配置
|
||||
* @return 字段命名策略,默认为camelCase
|
||||
*/
|
||||
private static String getFieldNaming(GenerationConfig config) {
|
||||
if (config != null && config.getExtraConfig() != null) {
|
||||
Map<String, Object> extraConfig = config.getExtraConfig();
|
||||
Object fieldNamingObj = extraConfig.get("fieldNaming");
|
||||
if (fieldNamingObj != null) {
|
||||
return fieldNamingObj.toString();
|
||||
}
|
||||
}
|
||||
return "camelCase"; // 默认使用驼峰命名
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线命名转换为大驼峰命名(首字母大写)
|
||||
*
|
||||
* @param name 名称,如 user_name
|
||||
* @return 大驼峰命名,如 UserName
|
||||
*/
|
||||
private static String toPascalCase(String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return "Unknown"; // 返回默认名称而不是null
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean nextUpperCase = true; // 首字母大写
|
||||
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char c = name.charAt(i);
|
||||
|
||||
if (c == '_') {
|
||||
nextUpperCase = true;
|
||||
} else {
|
||||
if (nextUpperCase) {
|
||||
result.append(Character.toUpperCase(c));
|
||||
nextUpperCase = false;
|
||||
} else {
|
||||
result.append(Character.toLowerCase(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果结果为空或无效,返回默认名称
|
||||
String entityName = result.toString();
|
||||
if (entityName.isEmpty()) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
// 检查是否是Java关键字,如果是则添加前缀
|
||||
if (isJavaKeyword(entityName)) {
|
||||
return "Table" + entityName;
|
||||
}
|
||||
|
||||
return entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线命名转换为小驼峰命名(首字母小写)
|
||||
*
|
||||
* @param name 名称,如 user_name
|
||||
* @return 小驼峰命名,如 userName
|
||||
*/
|
||||
private static String toCamelCase(String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return "unknown"; // 返回默认名称而不是null
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean nextUpperCase = false;
|
||||
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char c = name.charAt(i);
|
||||
|
||||
if (c == '_') {
|
||||
nextUpperCase = true;
|
||||
} else {
|
||||
if (nextUpperCase) {
|
||||
result.append(Character.toUpperCase(c));
|
||||
nextUpperCase = false;
|
||||
} else {
|
||||
if (result.length() == 0) {
|
||||
result.append(Character.toLowerCase(c)); // 首字母小写
|
||||
} else {
|
||||
result.append(Character.toLowerCase(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果结果为空或无效,返回默认名称
|
||||
String propertyName = result.toString();
|
||||
if (propertyName.isEmpty()) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
// 检查是否是Java关键字,如果是则添加前缀
|
||||
if (isJavaKeyword(propertyName)) {
|
||||
return "field" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
|
||||
}
|
||||
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否是Java关键字
|
||||
*
|
||||
* @param name 名称
|
||||
* @return 是否是Java关键字
|
||||
*/
|
||||
private static boolean isJavaKeyword(String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 常见的Java关键字列表
|
||||
String[] keywords = {
|
||||
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
|
||||
"const", "continue", "default", "do", "double", "else", "enum", "extends", "final",
|
||||
"finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int",
|
||||
"interface", "long", "native", "new", "null", "package", "private", "protected",
|
||||
"public", "return", "short", "static", "strictfp", "super", "switch", "synchronized",
|
||||
"this", "throw", "throws", "transient", "try", "void", "volatile", "while", "true",
|
||||
"false"
|
||||
};
|
||||
|
||||
for (String keyword : keywords) {
|
||||
if (keyword.equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查表是否应该被忽略
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @param config 生成配置
|
||||
* @return 是否应该忽略
|
||||
*/
|
||||
private static boolean shouldIgnoreTable(String tableName, GenerationConfig config) {
|
||||
if (config.getIgnoreTables() != null) {
|
||||
for (String ignoreTable : config.getIgnoreTables()) {
|
||||
if (ignoreTable.equalsIgnoreCase(tableName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除原来的mapDataType方法,因为现在使用TypeMappingConfig类
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.yexuejc.db2java.core.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据库类型到Java类型的映射配置类
|
||||
* 可维护的类型映射配置,支持多种数据库类型映射
|
||||
*
|
||||
* @author yexuejc
|
||||
* @since 2025-01
|
||||
*/
|
||||
public class TypeMappingConfig {
|
||||
|
||||
/**
|
||||
* 数据库类型到Java类型的映射表
|
||||
*/
|
||||
private static final Map<String, String> TYPE_MAPPING = new HashMap<>();
|
||||
|
||||
static {
|
||||
// MySQL类型映射
|
||||
TYPE_MAPPING.put("VARCHAR", "String");
|
||||
TYPE_MAPPING.put("CHAR", "String");
|
||||
TYPE_MAPPING.put("TEXT", "String");
|
||||
TYPE_MAPPING.put("TINYTEXT", "String");
|
||||
TYPE_MAPPING.put("MEDIUMTEXT", "String");
|
||||
TYPE_MAPPING.put("LONGTEXT", "String");
|
||||
|
||||
TYPE_MAPPING.put("INT", "Integer");
|
||||
TYPE_MAPPING.put("INTEGER", "Integer");
|
||||
TYPE_MAPPING.put("TINYINT", "Integer");
|
||||
TYPE_MAPPING.put("SMALLINT", "Integer");
|
||||
TYPE_MAPPING.put("MEDIUMINT", "Integer");
|
||||
TYPE_MAPPING.put("BIGINT", "Long");
|
||||
|
||||
TYPE_MAPPING.put("DECIMAL", "BigDecimal");
|
||||
TYPE_MAPPING.put("NUMERIC", "BigDecimal");
|
||||
|
||||
TYPE_MAPPING.put("DATE", "LocalDate");
|
||||
TYPE_MAPPING.put("TIME", "LocalTime");
|
||||
TYPE_MAPPING.put("DATETIME", "LocalDateTime");
|
||||
TYPE_MAPPING.put("TIMESTAMP", "LocalDateTime");
|
||||
|
||||
TYPE_MAPPING.put("BOOLEAN", "Boolean");
|
||||
TYPE_MAPPING.put("BIT", "Boolean");
|
||||
|
||||
TYPE_MAPPING.put("FLOAT", "Float");
|
||||
TYPE_MAPPING.put("DOUBLE", "Double");
|
||||
TYPE_MAPPING.put("REAL", "Double");
|
||||
|
||||
// PostgreSQL类型映射
|
||||
TYPE_MAPPING.put("CHARACTER VARYING", "String");
|
||||
TYPE_MAPPING.put("CHARACTER", "String");
|
||||
TYPE_MAPPING.put("TEXT", "String");
|
||||
|
||||
TYPE_MAPPING.put("SMALLINT", "Integer");
|
||||
TYPE_MAPPING.put("INTEGER", "Integer");
|
||||
TYPE_MAPPING.put("BIGINT", "Long");
|
||||
|
||||
TYPE_MAPPING.put("DECIMAL", "BigDecimal");
|
||||
TYPE_MAPPING.put("NUMERIC", "BigDecimal");
|
||||
|
||||
TYPE_MAPPING.put("DATE", "LocalDate");
|
||||
TYPE_MAPPING.put("TIME", "LocalTime");
|
||||
TYPE_MAPPING.put("TIMESTAMP", "LocalDateTime");
|
||||
TYPE_MAPPING.put("TIMESTAMP WITHOUT TIME ZONE", "LocalDateTime");
|
||||
|
||||
TYPE_MAPPING.put("BOOLEAN", "Boolean");
|
||||
|
||||
TYPE_MAPPING.put("REAL", "Float");
|
||||
TYPE_MAPPING.put("DOUBLE PRECISION", "Double");
|
||||
|
||||
// Oracle类型映射
|
||||
TYPE_MAPPING.put("VARCHAR2", "String");
|
||||
TYPE_MAPPING.put("NVARCHAR2", "String");
|
||||
TYPE_MAPPING.put("CHAR", "String");
|
||||
TYPE_MAPPING.put("NCHAR", "String");
|
||||
TYPE_MAPPING.put("CLOB", "String");
|
||||
|
||||
TYPE_MAPPING.put("NUMBER", "BigDecimal");
|
||||
TYPE_MAPPING.put("INTEGER", "Integer");
|
||||
|
||||
TYPE_MAPPING.put("DATE", "LocalDateTime");
|
||||
TYPE_MAPPING.put("TIMESTAMP", "LocalDateTime");
|
||||
|
||||
// SQL Server类型映射
|
||||
TYPE_MAPPING.put("NVARCHAR", "String");
|
||||
TYPE_MAPPING.put("NCHAR", "String");
|
||||
TYPE_MAPPING.put("NTEXT", "String");
|
||||
|
||||
TYPE_MAPPING.put("INT", "Integer");
|
||||
TYPE_MAPPING.put("BIGINT", "Long");
|
||||
|
||||
TYPE_MAPPING.put("DECIMAL", "BigDecimal");
|
||||
TYPE_MAPPING.put("NUMERIC", "BigDecimal");
|
||||
TYPE_MAPPING.put("MONEY", "BigDecimal");
|
||||
TYPE_MAPPING.put("SMALLMONEY", "BigDecimal");
|
||||
|
||||
TYPE_MAPPING.put("DATE", "LocalDate");
|
||||
TYPE_MAPPING.put("DATETIME", "LocalDateTime");
|
||||
TYPE_MAPPING.put("DATETIME2", "LocalDateTime");
|
||||
TYPE_MAPPING.put("SMALLDATETIME", "LocalDateTime");
|
||||
|
||||
TYPE_MAPPING.put("BIT", "Boolean");
|
||||
|
||||
TYPE_MAPPING.put("FLOAT", "Double");
|
||||
TYPE_MAPPING.put("REAL", "Float");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库类型对应的Java类型
|
||||
*
|
||||
* @param dbType 数据库类型
|
||||
* @return 对应的Java类型,如果未找到则返回Object
|
||||
*/
|
||||
public static String getJavaType(String dbType) {
|
||||
if (dbType == null || dbType.trim().isEmpty()) {
|
||||
return "Object";
|
||||
}
|
||||
|
||||
String upperDbType = dbType.trim().toUpperCase();
|
||||
String javaType = TYPE_MAPPING.get(upperDbType);
|
||||
|
||||
// 如果没有找到精确匹配,尝试模糊匹配
|
||||
if (javaType == null) {
|
||||
for (Map.Entry<String, String> entry : TYPE_MAPPING.entrySet()) {
|
||||
if (upperDbType.contains(entry.getKey()) || entry.getKey().contains(upperDbType)) {
|
||||
javaType = entry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return javaType != null ? javaType : "Object";
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加自定义类型映射
|
||||
*
|
||||
* @param dbType 数据库类型
|
||||
* @param javaType Java类型
|
||||
*/
|
||||
public static void addTypeMapping(String dbType, String javaType) {
|
||||
if (dbType != null && javaType != null) {
|
||||
TYPE_MAPPING.put(dbType.toUpperCase(), javaType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有类型映射
|
||||
*
|
||||
* @return 类型映射表的副本
|
||||
*/
|
||||
public static Map<String, String> getAllTypeMappings() {
|
||||
return new HashMap<>(TYPE_MAPPING);
|
||||
}
|
||||
}
|
||||
@@ -58,31 +58,43 @@ public class ${entity} {
|
||||
<% } %>
|
||||
<% /** -----------END 字段循环遍历----------- **/ %>
|
||||
|
||||
<% /** -----------BEGIN 一对一关联字段----------- **/ %>
|
||||
<% if(isNotEmpty(table.oneToOneFields)){ %>
|
||||
<% for(field in table.oneToOneFields){ %>
|
||||
|
||||
<% if(isNotEmpty(field.comment)){ %>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
<% } %>
|
||||
<% if(isNotEmpty(field.annotationAttributesList)){ %>
|
||||
<% for(an in field.annotationAttributesList){ %>
|
||||
${an.displayName}
|
||||
<% } %>
|
||||
<% } %>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% /** -----------END 一对一关联字段----------- **/ %>
|
||||
|
||||
<% /** -----------BEGIN 一对多关联字段----------- **/ %>
|
||||
<% if(isNotEmpty(table.oneToManyFields)){ %>
|
||||
<% for(field in table.oneToManyFields){ %>
|
||||
|
||||
<% if(isNotEmpty(field.comment)){ %>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
<% } %>
|
||||
<% if(isNotEmpty(field.annotationAttributesList)){ %>
|
||||
<% for(an in field.annotationAttributesList){ %>
|
||||
${an.displayName}
|
||||
<% } %>
|
||||
private java.util.List<${field.propertyType}> ${field.propertyName};
|
||||
<% } %>
|
||||
private List<${field.propertyType}> ${field.propertyName};
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% /** -----------END 一对多关联字段----------- **/ %>
|
||||
|
||||
<% if(!entityLombokModel){ %>
|
||||
<% for(field in table.fields){ %>
|
||||
|
||||
@@ -54,6 +54,42 @@ public class ${entity} {
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#-- ---------- BEGIN 一对一关联字段 ---------->
|
||||
<#if table.oneToOneFields??>
|
||||
<#list table.oneToOneFields as field>
|
||||
|
||||
<#if field.comment!?length gt 0>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
<#if field.annotationAttributesList??>
|
||||
<#list field.annotationAttributesList as an>
|
||||
${an.displayName}
|
||||
</#list>
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
</#if>
|
||||
<#-- ---------- END 一对一关联字段 ---------->
|
||||
<#-- ---------- BEGIN 一对多关联字段 ---------->
|
||||
<#if table.oneToManyFields??>
|
||||
<#list table.oneToManyFields as field>
|
||||
|
||||
<#if field.comment!?length gt 0>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
<#if field.annotationAttributesList??>
|
||||
<#list field.annotationAttributesList as an>
|
||||
${an.displayName}
|
||||
</#list>
|
||||
</#if>
|
||||
private java.util.List<${field.propertyType}> ${field.propertyName};
|
||||
</#list>
|
||||
</#if>
|
||||
<#-- ---------- END 一对多关联字段 ---------->
|
||||
<#if !entityLombokModel>
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
|
||||
@@ -59,12 +59,16 @@ public class ${entity} {
|
||||
#if(${table.oneToOneFields})
|
||||
#foreach($field in ${table.oneToOneFields})
|
||||
|
||||
#if("$!field.comment" != "")
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
#foreach($an in ${field.annotationAttributesList})
|
||||
#end
|
||||
#if(${field.annotationAttributesList})
|
||||
#foreach($an in ${field.annotationAttributesList})
|
||||
${an.displayName}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
#end
|
||||
#end
|
||||
@@ -74,13 +78,17 @@ public class ${entity} {
|
||||
#if(${table.oneToManyFields})
|
||||
#foreach($field in ${table.oneToManyFields})
|
||||
|
||||
#if("$!field.comment" != "")
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
#foreach($an in ${field.annotationAttributesList})
|
||||
#end
|
||||
#if(${field.annotationAttributesList})
|
||||
#foreach($an in ${field.annotationAttributesList})
|
||||
${an.displayName}
|
||||
#end
|
||||
private java.util.List<${field.propertyType}> ${field.propertyName};
|
||||
#end
|
||||
#end
|
||||
private List<${field.propertyType}> ${field.propertyName};
|
||||
#end
|
||||
#end
|
||||
## ---------- END 一对多关联字段 ----------
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.yexuejc.db2java.core;
|
||||
|
||||
import com.yexuejc.db2java.core.generator.GenerationConfig;
|
||||
import com.yexuejc.db2java.core.generator.GenerationResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
class MysqlDb2JavaCoreTest {
|
||||
|
||||
@Test
|
||||
void generate() throws Exception {
|
||||
// 创建配置对象并设置相关属性
|
||||
GenerationConfig config = new GenerationConfig();
|
||||
config.setUrl("jdbc:mysql://192.168.0.107:3306/globalVoice?characterEncoding=utf8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true");
|
||||
config.setUsername("intasect");
|
||||
config.setPassword("2$hGv1Dz[3)J7]BS]");
|
||||
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
|
||||
config.setMode("mybatis-plus");
|
||||
config.setType("coding");
|
||||
config.setOutDir("C:/0110_Workspace/yexuejc/db2java/export");
|
||||
config.setPackageName("top.yexuejc.abc");
|
||||
config.setAuthor("yexuejc");
|
||||
config.setLombok(false);
|
||||
config.setMerge(true);
|
||||
config.setOverride(true);
|
||||
config.setEngine("freemarker");
|
||||
|
||||
config.setExtraConfig(Map.of("fieldNaming","camelCase"));
|
||||
|
||||
// 设置忽略表列表
|
||||
config.setIgnoreTables(List.of("sys_user", "sys_role", "sys_role_user").toArray(new String[0]));
|
||||
|
||||
// 设置忽略字段列表
|
||||
config.setIgnoreColumns(List.of("create_time", "update_time").toArray(new String[0]));
|
||||
|
||||
// 设置包含表列表
|
||||
// config.setIncludeTables(List.of("sys_user", "sys_role", "sys_role_user").toArray(new String[0]));
|
||||
|
||||
// 执行代码生成
|
||||
GenerationResult result = Db2JavaCore.generate(config);
|
||||
|
||||
System.out.println(result);
|
||||
|
||||
// 验证结果不为空
|
||||
assertNotNull(result);
|
||||
}
|
||||
}
|
||||
@@ -28,27 +28,27 @@ public class Db2JavaExample {
|
||||
// 测试生成标准的Java代码
|
||||
// 设置为coding模式,生成标准的src/main/java结构
|
||||
testImprovedGeneration(tableInfos, "freemarker", "mybatis", true,"coding");// 基本的OK
|
||||
testImprovedGeneration(tableInfos, "freemarker", "mybatis", false,"coding");// 基本的OK
|
||||
testImprovedGeneration(tableInfos, "freemarker", "mybatis", false,"file");// 基本的OK
|
||||
testImprovedGeneration(tableInfos, "freemarker", "mybatis-plus", true,"coding");// 基本的OK
|
||||
testImprovedGeneration(tableInfos, "freemarker", "jpa", false,"coding");// 测试不使用Lombok的情况
|
||||
testImprovedGeneration(tableInfos, "freemarker", "jpa", true,"coding");// 基本的OK
|
||||
// testImprovedGeneration(tableInfos, "freemarker", "mybatis", false,"coding");// 基本的OK
|
||||
// testImprovedGeneration(tableInfos, "freemarker", "mybatis", false,"file");// 基本的OK
|
||||
// testImprovedGeneration(tableInfos, "freemarker", "mybatis-plus", true,"coding");// 基本的OK
|
||||
// testImprovedGeneration(tableInfos, "freemarker", "jpa", false,"coding");// 测试不使用Lombok的情况
|
||||
// testImprovedGeneration(tableInfos, "freemarker", "jpa", true,"coding");// 基本的OK
|
||||
|
||||
// velocity,beetl,enjoy
|
||||
|
||||
testImprovedGeneration(tableInfos, "velocity", "mybatis", true,"coding");
|
||||
testImprovedGeneration(tableInfos, "velocity", "mybatis", false,"coding");
|
||||
testImprovedGeneration(tableInfos, "velocity", "mybatis", false,"file");
|
||||
testImprovedGeneration(tableInfos, "velocity", "mybatis-plus", true,"coding");
|
||||
testImprovedGeneration(tableInfos, "velocity", "hibernate", false,"coding");
|
||||
testImprovedGeneration(tableInfos, "velocity", "jpa", true,"coding");
|
||||
// testImprovedGeneration(tableInfos, "velocity", "mybatis", false,"coding");
|
||||
// testImprovedGeneration(tableInfos, "velocity", "mybatis", false,"file");
|
||||
// testImprovedGeneration(tableInfos, "velocity", "mybatis-plus", true,"coding");
|
||||
// testImprovedGeneration(tableInfos, "velocity", "hibernate", false,"coding");
|
||||
// testImprovedGeneration(tableInfos, "velocity", "jpa", true,"coding");
|
||||
|
||||
testImprovedGeneration(tableInfos, "beetl", "mybatis", true,"coding");
|
||||
testImprovedGeneration(tableInfos, "beetl", "mybatis", false,"coding");
|
||||
testImprovedGeneration(tableInfos, "beetl", "mybatis", false,"file");
|
||||
testImprovedGeneration(tableInfos, "beetl", "mybatis-plus", true,"coding");
|
||||
testImprovedGeneration(tableInfos, "beetl", "hibernate", false,"coding");
|
||||
testImprovedGeneration(tableInfos, "beetl", "jpa", true,"coding");
|
||||
// testImprovedGeneration(tableInfos, "beetl", "mybatis", false,"coding");
|
||||
// testImprovedGeneration(tableInfos, "beetl", "mybatis", false,"file");
|
||||
// testImprovedGeneration(tableInfos, "beetl", "mybatis-plus", true,"coding");
|
||||
// testImprovedGeneration(tableInfos, "beetl", "hibernate", false,"coding");
|
||||
// testImprovedGeneration(tableInfos, "beetl", "jpa", true,"coding");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("生成代码时发生错误: " + e.getMessage());
|
||||
|
||||
@@ -2,116 +2,83 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.5.6</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>top.yexuejc</groupId>
|
||||
<artifactId>db2java-web</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>db2java-web</name>
|
||||
<description>Web interface for db2java code generation tool</description>
|
||||
|
||||
<properties>
|
||||
<compiler-plugin.version>3.14.0</compiler-plugin.version>
|
||||
<maven.compiler.release>24</maven.compiler.release>
|
||||
<java.version>17</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||
<quarkus.platform.version>3.26.3</quarkus.platform.version>
|
||||
<skipITs>true</skipITs>
|
||||
<surefire-plugin.version>3.5.3</surefire-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>${quarkus.platform.artifact-id}</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Starter Web with Undertow -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Thymeleaf for UI -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Configuration Processor -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Starter Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- db2java-core dependency -->
|
||||
<dependency>
|
||||
<groupId>top.yexuejc</groupId>
|
||||
<artifactId>db2java-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
<goal>generate-code</goal>
|
||||
<goal>generate-code-tests</goal>
|
||||
<goal>native-image-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<parameters>true</parameters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner
|
||||
</native.image.path>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.yexuejc.db2java.web;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.yexuejc.db2java.web.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "datasource")
|
||||
public class DataSourceProperties {
|
||||
private String url;
|
||||
private String username;
|
||||
private String password;
|
||||
private String driverClassName;
|
||||
|
||||
// Getters and Setters
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getDriverClassName() {
|
||||
return driverClassName;
|
||||
}
|
||||
|
||||
public void setDriverClassName(String driverClassName) {
|
||||
this.driverClassName = driverClassName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
package com.yexuejc.db2java.web.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "generate")
|
||||
public class GenerateProperties {
|
||||
private String mode;
|
||||
private String type;
|
||||
private String out;
|
||||
private String packageName;
|
||||
private String author;
|
||||
private boolean lombok;
|
||||
private boolean merge;
|
||||
private boolean override;
|
||||
private String engine;
|
||||
private List<String> ignoreTable;
|
||||
private List<String> ignoreColumn;
|
||||
private List<String> includeTable;
|
||||
private Entity entity = new Entity();
|
||||
private Controller controller = new Controller();
|
||||
|
||||
public static class Entity {
|
||||
private boolean serialVersionUID;
|
||||
private boolean serialAnnotation;
|
||||
private boolean columnConstant;
|
||||
private boolean chainModel;
|
||||
private boolean toString;
|
||||
private boolean fieldUseJavaDoc;
|
||||
private boolean activeRecord;
|
||||
private boolean serializable;
|
||||
private boolean equalsAndHashCode;
|
||||
private String fieldNaming;
|
||||
private String tableAnnotation;
|
||||
|
||||
// Getters and Setters
|
||||
public boolean isSerialVersionUID() {
|
||||
return serialVersionUID;
|
||||
}
|
||||
|
||||
public void setSerialVersionUID(boolean serialVersionUID) {
|
||||
this.serialVersionUID = serialVersionUID;
|
||||
}
|
||||
|
||||
public boolean isSerialAnnotation() {
|
||||
return serialAnnotation;
|
||||
}
|
||||
|
||||
public void setSerialAnnotation(boolean serialAnnotation) {
|
||||
this.serialAnnotation = serialAnnotation;
|
||||
}
|
||||
|
||||
public boolean isColumnConstant() {
|
||||
return columnConstant;
|
||||
}
|
||||
|
||||
public void setColumnConstant(boolean columnConstant) {
|
||||
this.columnConstant = columnConstant;
|
||||
}
|
||||
|
||||
public boolean isChainModel() {
|
||||
return chainModel;
|
||||
}
|
||||
|
||||
public void setChainModel(boolean chainModel) {
|
||||
this.chainModel = chainModel;
|
||||
}
|
||||
|
||||
public boolean isToString() {
|
||||
return toString;
|
||||
}
|
||||
|
||||
public void setToString(boolean toString) {
|
||||
this.toString = toString;
|
||||
}
|
||||
|
||||
public boolean isFieldUseJavaDoc() {
|
||||
return fieldUseJavaDoc;
|
||||
}
|
||||
|
||||
public void setFieldUseJavaDoc(boolean fieldUseJavaDoc) {
|
||||
this.fieldUseJavaDoc = fieldUseJavaDoc;
|
||||
}
|
||||
|
||||
public boolean isActiveRecord() {
|
||||
return activeRecord;
|
||||
}
|
||||
|
||||
public void setActiveRecord(boolean activeRecord) {
|
||||
this.activeRecord = activeRecord;
|
||||
}
|
||||
|
||||
public boolean isSerializable() {
|
||||
return serializable;
|
||||
}
|
||||
|
||||
public void setSerializable(boolean serializable) {
|
||||
this.serializable = serializable;
|
||||
}
|
||||
|
||||
public boolean isEqualsAndHashCode() {
|
||||
return equalsAndHashCode;
|
||||
}
|
||||
|
||||
public void setEqualsAndHashCode(boolean equalsAndHashCode) {
|
||||
this.equalsAndHashCode = equalsAndHashCode;
|
||||
}
|
||||
|
||||
public String getFieldNaming() {
|
||||
return fieldNaming;
|
||||
}
|
||||
|
||||
public void setFieldNaming(String fieldNaming) {
|
||||
this.fieldNaming = fieldNaming;
|
||||
}
|
||||
|
||||
public String getTableAnnotation() {
|
||||
return tableAnnotation;
|
||||
}
|
||||
|
||||
public void setTableAnnotation(String tableAnnotation) {
|
||||
this.tableAnnotation = tableAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Controller {
|
||||
private boolean mappingHyphen;
|
||||
private boolean restStyle;
|
||||
private String superClass;
|
||||
|
||||
// Getters and Setters
|
||||
public boolean isMappingHyphen() {
|
||||
return mappingHyphen;
|
||||
}
|
||||
|
||||
public void setMappingHyphen(boolean mappingHyphen) {
|
||||
this.mappingHyphen = mappingHyphen;
|
||||
}
|
||||
|
||||
public boolean isRestStyle() {
|
||||
return restStyle;
|
||||
}
|
||||
|
||||
public void setRestStyle(boolean restStyle) {
|
||||
this.restStyle = restStyle;
|
||||
}
|
||||
|
||||
public String getSuperClass() {
|
||||
return superClass;
|
||||
}
|
||||
|
||||
public void setSuperClass(String superClass) {
|
||||
this.superClass = superClass;
|
||||
}
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setMode(String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getOut() {
|
||||
return out;
|
||||
}
|
||||
|
||||
public void setOut(String out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public boolean isLombok() {
|
||||
return lombok;
|
||||
}
|
||||
|
||||
public void setLombok(boolean lombok) {
|
||||
this.lombok = lombok;
|
||||
}
|
||||
|
||||
public boolean isMerge() {
|
||||
return merge;
|
||||
}
|
||||
|
||||
public void setMerge(boolean merge) {
|
||||
this.merge = merge;
|
||||
}
|
||||
|
||||
public boolean isOverride() {
|
||||
return override;
|
||||
}
|
||||
|
||||
public void setOverride(boolean override) {
|
||||
this.override = override;
|
||||
}
|
||||
|
||||
public String getEngine() {
|
||||
return engine;
|
||||
}
|
||||
|
||||
public void setEngine(String engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
public List<String> getIgnoreTable() {
|
||||
return ignoreTable;
|
||||
}
|
||||
|
||||
public void setIgnoreTable(List<String> ignoreTable) {
|
||||
this.ignoreTable = ignoreTable;
|
||||
}
|
||||
|
||||
public List<String> getIgnoreColumn() {
|
||||
return ignoreColumn;
|
||||
}
|
||||
|
||||
public void setIgnoreColumn(List<String> ignoreColumn) {
|
||||
this.ignoreColumn = ignoreColumn;
|
||||
}
|
||||
|
||||
public List<String> getIncludeTable() {
|
||||
return includeTable;
|
||||
}
|
||||
|
||||
public void setIncludeTable(List<String> includeTable) {
|
||||
this.includeTable = includeTable;
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(Entity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public Controller getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public void setController(Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package com.yexuejc.db2java.web.controller;
|
||||
|
||||
import com.yexuejc.db2java.core.Db2JavaCore;
|
||||
import com.yexuejc.db2java.core.generator.GenerationConfig;
|
||||
import com.yexuejc.db2java.core.generator.GenerationResult;
|
||||
import com.yexuejc.db2java.web.config.DataSourceProperties;
|
||||
import com.yexuejc.db2java.web.config.GenerateProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
public class CodeGeneratorController {
|
||||
|
||||
@Autowired
|
||||
private DataSourceProperties dataSourceProperties;
|
||||
|
||||
@Autowired
|
||||
private GenerateProperties generateProperties;
|
||||
|
||||
@GetMapping("/")
|
||||
public String index(Model model) {
|
||||
model.addAttribute("dataSourceProperties", dataSourceProperties);
|
||||
model.addAttribute("generateProperties", generateProperties);
|
||||
String separator = System.lineSeparator();
|
||||
model.addAttribute("separator", separator);
|
||||
return "index";
|
||||
}
|
||||
|
||||
@PostMapping("/generate")
|
||||
public String generateCode(
|
||||
@RequestParam String url,
|
||||
@RequestParam String username,
|
||||
@RequestParam String password,
|
||||
@RequestParam String driverClassName,
|
||||
@RequestParam String mode,
|
||||
@RequestParam String type,
|
||||
@RequestParam String out,
|
||||
@RequestParam String packageName,
|
||||
@RequestParam String author,
|
||||
@RequestParam(defaultValue = "false") boolean lombok,
|
||||
@RequestParam(defaultValue = "false") boolean merge,
|
||||
@RequestParam(defaultValue = "false") boolean override,
|
||||
@RequestParam String engine,
|
||||
@RequestParam(required = false) String ignoreTable,
|
||||
@RequestParam(required = false) String ignoreColumn,
|
||||
@RequestParam(required = false) String includeTable,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
System.out.println("接收到代码生成请求,参数如下:");
|
||||
System.out.println("数据库URL: " + url);
|
||||
System.out.println("数据库用户名: " + username);
|
||||
System.out.println("数据库驱动类名: " + driverClassName);
|
||||
System.out.println("生成模式: " + mode);
|
||||
System.out.println("生成代码模式: " + type);
|
||||
System.out.println("输出目录: " + out);
|
||||
System.out.println("包名: " + packageName);
|
||||
System.out.println("作者: " + author);
|
||||
System.out.println("是否启用Lombok: " + lombok);
|
||||
System.out.println("是否启用合并模式: " + merge);
|
||||
System.out.println("是否覆盖文件: " + override);
|
||||
System.out.println("模板引擎: " + engine);
|
||||
System.out.println("忽略表列表: " + ignoreTable);
|
||||
System.out.println("忽略字段列表: " + ignoreColumn);
|
||||
System.out.println("包含表列表: " + includeTable);
|
||||
System.out.println("===========================================");
|
||||
|
||||
try {
|
||||
// 更新配置
|
||||
dataSourceProperties.setUrl(url);
|
||||
dataSourceProperties.setUsername(username);
|
||||
dataSourceProperties.setPassword(password);
|
||||
dataSourceProperties.setDriverClassName(driverClassName);
|
||||
|
||||
generateProperties.setMode(mode);
|
||||
generateProperties.setType(type);
|
||||
generateProperties.setOut(out);
|
||||
generateProperties.setPackageName(packageName);
|
||||
generateProperties.setAuthor(author);
|
||||
generateProperties.setLombok(lombok);
|
||||
generateProperties.setMerge(merge);
|
||||
generateProperties.setOverride(override);
|
||||
generateProperties.setEngine(engine);
|
||||
generateProperties.setIgnoreTable(ignoreTable != null && !ignoreTable.isEmpty() ?
|
||||
Arrays.asList(ignoreTable.split("[\\r\\n]+")) : null);
|
||||
generateProperties.setIgnoreColumn(ignoreColumn != null && !ignoreColumn.isEmpty() ?
|
||||
Arrays.asList(ignoreColumn.split("[\\r\\n]+")) : null);
|
||||
generateProperties.setIncludeTable(includeTable != null && !includeTable.isEmpty() ?
|
||||
Arrays.asList(includeTable.split("[\\r\\n]+")) : null);
|
||||
|
||||
// 创建生成配置
|
||||
GenerationConfig config = new GenerationConfig();
|
||||
config.setUrl(url);
|
||||
config.setUsername(username);
|
||||
config.setPassword(password);
|
||||
config.setDriverClassName(driverClassName);
|
||||
config.setMode(mode);
|
||||
config.setType(type);
|
||||
config.setOutDir(out);
|
||||
config.setPackageName(packageName);
|
||||
config.setAuthor(author);
|
||||
config.setLombok(lombok);
|
||||
config.setMerge(merge);
|
||||
config.setOverride(override);
|
||||
config.setEngine(engine);
|
||||
|
||||
// 处理忽略表列表
|
||||
if (ignoreTable != null && !ignoreTable.isEmpty()) {
|
||||
List<String> ignoreTableList = Arrays.stream(ignoreTable.split("[\\r\\n]+"))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
config.setIgnoreTables(ignoreTableList.toArray(new String[0]));
|
||||
} else {
|
||||
config.setIgnoreTables(new String[0]);
|
||||
}
|
||||
|
||||
// 处理忽略字段列表
|
||||
if (ignoreColumn != null && !ignoreColumn.isEmpty()) {
|
||||
List<String> ignoreColumnList = Arrays.stream(ignoreColumn.split("[\\r\\n]+"))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
config.setIgnoreColumns(ignoreColumnList.toArray(new String[0]));
|
||||
} else {
|
||||
config.setIgnoreColumns(new String[0]);
|
||||
}
|
||||
|
||||
// 处理包含表列表
|
||||
if (includeTable != null && !includeTable.isEmpty()) {
|
||||
List<String> includeTableList = Arrays.stream(includeTable.split("[\\r\\n]+"))
|
||||
.map(String::trim)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
config.setIncludeTables(includeTableList.toArray(new String[0]));
|
||||
} else {
|
||||
config.setIncludeTables(new String[0]);
|
||||
}
|
||||
|
||||
// 设置额外配置,包括字段命名策略
|
||||
Map<String, Object> extraConfig = new HashMap<>();
|
||||
extraConfig.put("fieldNaming", generateProperties.getEntity().getFieldNaming());
|
||||
config.setExtraConfig(extraConfig);
|
||||
|
||||
// 执行代码生成
|
||||
GenerationResult result = Db2JavaCore.generate(config);
|
||||
|
||||
redirectAttributes.addFlashAttribute("success", "代码生成成功!共生成 " + result.getGeneratedFiles().size() + " 个文件。");
|
||||
} catch (Exception e) {
|
||||
System.err.println("代码生成失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
redirectAttributes.addFlashAttribute("error", "代码生成失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
return "redirect:/";
|
||||
}
|
||||
}
|
||||
88
db2java-web/src/main/resources/application.yml
Normal file
88
db2java-web/src/main/resources/application.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
server:
|
||||
port: 8080
|
||||
undertow:
|
||||
# 设置IO线程数, 它主要执行非阻塞的任务, 它们会负责多个连接
|
||||
io-threads: 4
|
||||
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程
|
||||
worker-threads: 20
|
||||
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
|
||||
buffer-size: 1024
|
||||
# 是否分配的直接内存
|
||||
direct-buffers: true
|
||||
|
||||
# 数据库配置
|
||||
datasource:
|
||||
url: jdbc:mysql://192.168.0.107:3306/globalVoice?characterEncoding=utf8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: intasect
|
||||
password: 2$hGv1Dz[3)J7]BS]
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
||||
# 生成配置信息
|
||||
generate:
|
||||
# 生成模式:hibernate,jpa,mybatis,mybatis-plus
|
||||
mode: mybatis-plus
|
||||
# 生成代码模式 file(直接在指定目录下生成代码),coding(在目录下生成/src/main/java和对应的package路径)
|
||||
type: coding
|
||||
# 输出目录
|
||||
out: C:/0110_Workspace/yexuejc/db2java/export
|
||||
# 包名
|
||||
package: com.yexuejc.db2java.export
|
||||
# 作者
|
||||
author: yexuejc
|
||||
# lombok模式 - 启用后不生成getter/setter方法,使用@Data注解
|
||||
lombok: false
|
||||
# merge模式 - 是否合并已存在的文件
|
||||
merge: true
|
||||
# 覆盖已存在文件
|
||||
override: true
|
||||
# 模板引擎:freemarker,velocity,beetl,enjoy
|
||||
engine: freemarker
|
||||
# 忽略表
|
||||
ignore-table:
|
||||
- sys_user
|
||||
- sys_role
|
||||
- sys_role_user
|
||||
# 忽略字段
|
||||
ignore-column:
|
||||
- create_time
|
||||
- update_time
|
||||
# 包含表
|
||||
include-table:
|
||||
- sys_user
|
||||
- sys_role
|
||||
- sys_role_user
|
||||
# 实体类配置
|
||||
entity:
|
||||
# 是否生成序列化版本ID
|
||||
serialVersionUID: true
|
||||
# 是否使用Serial注解(Java 14+)
|
||||
serialAnnotation: false
|
||||
# 是否生成字段常量
|
||||
columnConstant: false
|
||||
# 是否启用链式模型(返回this)
|
||||
chainModel: false
|
||||
# 是否生成toString方法(lombok=false时有效)
|
||||
toString: true
|
||||
# 是否使用JavaDoc注释字段
|
||||
fieldUseJavaDoc: true
|
||||
# 是否启用ActiveRecord模式
|
||||
activeRecord: false
|
||||
# 是否实现Serializable接口
|
||||
serializable: true
|
||||
# 是否生成equals和hashCode方法
|
||||
equalsAndHashCode: false
|
||||
# 字段命名策略: camelCase(驼峰), underline(下划线)
|
||||
fieldNaming: camelCase
|
||||
# 表名注解策略: none(无注解), table(使用@Table), entity(使用@Entity)
|
||||
tableAnnotation: none
|
||||
controller:
|
||||
# 驼峰转连字符(默认 false)
|
||||
## <code>@RequestMapping("/managerUserActionHistory")</code> -> <code>@RequestMapping("/manager-user-action-history")</code>
|
||||
mappingHyphen: true
|
||||
# 生成 <code>@RestController</code> 控制器(默认 false)
|
||||
## <code>@Controller</code> -> <code>@RestController</code>
|
||||
restStyle: true
|
||||
# 自定义继承的Controller类全称,带包名,默认为空
|
||||
## superClass: com.yexuejc.db2java.export.controller.BaseController
|
||||
superClass:
|
||||
|
||||
179
db2java-web/src/main/resources/templates/index.html
Normal file
179
db2java-web/src/main/resources/templates/index.html
Normal file
@@ -0,0 +1,179 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DB2Java代码生成器</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h1 class="mb-4">DB2Java代码生成器</h1>
|
||||
|
||||
<!-- 显示成功或错误消息 -->
|
||||
<div th:if="${success}" class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<span th:text="${success}"></span>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div th:if="${error}" class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<span th:text="${error}"></span>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<form action="/generate" method="post">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5>数据库配置</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="url" class="form-label">数据库URL</label>
|
||||
<input type="text" class="form-control" id="url" name="url"
|
||||
th:value="${dataSourceProperties.url}" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="driverClassName" class="form-label">驱动类名</label>
|
||||
<input type="text" class="form-control" id="driverClassName" name="driverClassName"
|
||||
th:value="${dataSourceProperties.driverClassName}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="username" class="form-label">用户名</label>
|
||||
<input type="text" class="form-control" id="username" name="username"
|
||||
th:value="${dataSourceProperties.username}" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="password" class="form-label">密码</label>
|
||||
<input type="password" class="form-control" id="password" name="password"
|
||||
th:value="${dataSourceProperties.password}" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5>生成配置</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="mode" class="form-label">生成模式</label>
|
||||
<select class="form-select" id="mode" name="mode" required>
|
||||
<option value="hibernate" th:selected="${generateProperties.mode == 'hibernate'}">
|
||||
Hibernate
|
||||
</option>
|
||||
<option value="jpa" th:selected="${generateProperties.mode == 'jpa'}">JPA</option>
|
||||
<option value="mybatis" th:selected="${generateProperties.mode == 'mybatis'}">MyBatis
|
||||
</option>
|
||||
<option value="mybatis-plus" th:selected="${generateProperties.mode == 'mybatis-plus'}">
|
||||
MyBatis-Plus
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="type" class="form-label">生成代码模式</label>
|
||||
<select class="form-select" id="type" name="type" required>
|
||||
<option value="file" th:selected="${generateProperties.type == 'file'}">File</option>
|
||||
<option value="coding" th:selected="${generateProperties.type == 'coding'}">Coding</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="out" class="form-label">输出目录</label>
|
||||
<input type="text" class="form-control" id="out" name="out"
|
||||
th:value="${generateProperties.out}" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="packageName" class="form-label">包名</label>
|
||||
<input type="text" class="form-control" id="packageName" name="packageName"
|
||||
th:value="${generateProperties.packageName}" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="author" class="form-label">作者</label>
|
||||
<input type="text" class="form-control" id="author" name="author"
|
||||
th:value="${generateProperties.author}">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="engine" class="form-label">模板引擎</label>
|
||||
<select class="form-select" id="engine" name="engine" required>
|
||||
<option value="freemarker" th:selected="${generateProperties.engine == 'freemarker'}">
|
||||
FreeMarker
|
||||
</option>
|
||||
<option value="velocity" th:selected="${generateProperties.engine == 'velocity'}">Velocity
|
||||
</option>
|
||||
<option value="beetl" th:selected="${generateProperties.engine == 'beetl'}">Beetl</option>
|
||||
<option value="enjoy" th:selected="${generateProperties.engine == 'enjoy'}">Enjoy</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="lombok" name="lombok"
|
||||
th:checked="${generateProperties.lombok}">
|
||||
<label class="form-check-label" for="lombok">启用Lombok</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="merge" name="merge"
|
||||
th:checked="${generateProperties.merge}">
|
||||
<label class="form-check-label" for="merge">合并模式</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="override" name="override"
|
||||
th:checked="${generateProperties.override}">
|
||||
<label class="form-check-label" for="override">覆盖文件</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5>表和字段配置</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="includeTable" class="form-label">包含表(每行一个)</label>
|
||||
<textarea class="form-control" id="includeTable" name="includeTable" rows="3"
|
||||
th:text="${generateProperties?.includeTable != null ? #strings.listJoin(generateProperties.includeTable, separator) : ''}">
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="ignoreTable" class="form-label">忽略表(每行一个)</label>
|
||||
<textarea class="form-control" id="ignoreTable" name="ignoreTable" rows="3"
|
||||
th:text="${generateProperties?.ignoreTable != null ? #strings.listJoin(generateProperties.ignoreTable, separator) : ''}"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="ignoreColumn" class="form-label">忽略字段(每行一个)</label>
|
||||
<textarea class="form-control" id="ignoreColumn" name="ignoreColumn" rows="3"
|
||||
th:text="${generateProperties?.ignoreColumn != null ? #strings.listJoin(generateProperties.ignoreColumn, separator) : ''}"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<button type="submit" class="btn btn-primary btn-lg">生成代码</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
7
问题修改一览.csv
Normal file
7
问题修改一览.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
问题点,对应方案,类似问题是否对应
|
||||
HTML表单请求参数与接口定义不匹配导致400错误,将Controller中List<String>参数类型改为String,并在代码中进行分割处理,是
|
||||
可选复选框参数缺失导致400错误,为lombok、merge、override参数添加@RequestParam(defaultValue = "false")注解,是
|
||||
换行符处理不一致,将字符串分割逻辑从"\\r?\\n"修改为"[\\r\\n]+"正则表达式,是
|
||||
字段命名策略未生效,在DatabaseUtils中正确获取和使用fieldNaming配置,是
|
||||
模板处理器接口实现不完整,添加templateExists方法实现并修复导入语句,是
|
||||
数据库字段和Java属性类型映射不正确,创建TypeMappingConfig配置类进行类型映射,是
|
||||
|
Can't render this file because it contains an unexpected character in line 3 and column 113.
|
8
问题修改一览.txt
Normal file
8
问题修改一览.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
问题点,对应案,类似问题是否对应
|
||||
1. HTML表单参数与Controller接口参数类型不匹配导致400错误,修改Controller中ignoreTable、ignoreColumn、includeTable参数类型从List<String>为String,并在代码中进行分割处理,是
|
||||
2. HTML表单中可选复选框未选中时不会发送参数导致400错误,为lombok、merge、override参数添加@RequestParam(defaultValue = "false")注解,是
|
||||
3. 不同操作系统的换行符处理不一致,将字符串分割逻辑从"\\r?\\n"修改为"[\\r\\n]+"正则表达式,是
|
||||
4. 字段命名策略配置未生效,修复DatabaseUtils中字段命名转换逻辑,正确使用fieldNaming配置,是
|
||||
5. 实体类名大小写不正确,class名应使用大驼峰命名,修复DatabaseUtils中的toPascalCase方法,是
|
||||
6. 无效表名导致生成null.java文件,增加表名有效性检查和默认名称处理机制,是
|
||||
7. 模板引擎类名与文件名不一致,重构FreemarkerTemplateProcessor确保类名和文件名一致,是
|
||||
Reference in New Issue
Block a user