diff --git a/db2java-core/pom.xml b/db2java-core/pom.xml index ad1f129..a1e531d 100644 --- a/db2java-core/pom.xml +++ b/db2java-core/pom.xml @@ -97,6 +97,12 @@ logback-classic 1.4.8 + + + org.projectlombok + lombok + 1.18.40 + \ No newline at end of file diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/HibernateCodeGenerator.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/HibernateCodeGenerator.java index 5442c4d..caa88c2 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/HibernateCodeGenerator.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/HibernateCodeGenerator.java @@ -66,7 +66,7 @@ public class HibernateCodeGenerator implements CodeGenerator { private GeneratedFile generateEntity(TableInfo tableInfo, GenerationConfig config) { try { String fileName = tableInfo.getEntityName() + ".java"; - String filePath = config.getOutputPath() + "/entity/" + fileName; + String filePath = buildFilePath(config, "entity", fileName); // 获取模板引擎处理器 TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); @@ -85,6 +85,23 @@ public class HibernateCodeGenerator implements CodeGenerator { } } + /** + * 构建文件路径,根据type配置决定路径结构 + */ + private String buildFilePath(GenerationConfig config, String subDir, String fileName) { + String basePath = config.getOutputPath(); + String type = config.getType(); + + if ("coding".equals(type)) { + // coding模式:生成标准的src/main/java结构 + String packagePath = config.getPackageName().replace(".", "/"); + return basePath + "/src/main/java/" + packagePath + "/" + subDir + "/" + fileName; + } else { + // file模式:直接在指定目录下生成 + return basePath + "/" + subDir + "/" + fileName; + } + } + /** * 构建模板数据模型 */ @@ -98,9 +115,26 @@ public class HibernateCodeGenerator implements CodeGenerator { dataModel.put("entity", tableInfo.getEntityName()); dataModel.put("table", createTableMap(tableInfo)); + // 导入包 + dataModel.put("importEntityFrameworkPackages", getEntityImports(config.isLombok())); + dataModel.put("importEntityJavaPackages", getJavaImports(tableInfo)); + // Lombok配置 dataModel.put("entityLombokModel", config.isLombok()); + // 类注解(默认为空列表) + dataModel.put("entityClassAnnotations", new ArrayList<>()); + + // 实体类配置 + dataModel.put("superEntityClass", null); + dataModel.put("activeRecord", false); + dataModel.put("entitySerialVersionUID", true); + dataModel.put("entitySerialAnnotation", false); + dataModel.put("chainModel", false); + dataModel.put("entityColumnConstant", false); + dataModel.put("entityToString", false); + dataModel.put("entityFieldUseJavaDoc", true); + // 从extraConfig中获取扩展配置 Map extraConfig = config.getExtraConfig(); if (extraConfig != null) { @@ -114,6 +148,16 @@ public class HibernateCodeGenerator implements CodeGenerator { // 字段相关配置 dataModel.put("fieldUseJavaDoc", extraConfig.getOrDefault("fieldUseJavaDoc", true)); + // 类注解 + dataModel.put("entityClassAnnotations", extraConfig.getOrDefault("entityClassAnnotations", new ArrayList<>())); + + // 实体类配置 + dataModel.put("superEntityClass", extraConfig.get("superEntityClass")); + dataModel.put("activeRecord", extraConfig.getOrDefault("activeRecord", false)); + dataModel.put("entitySerialAnnotation", extraConfig.getOrDefault("entitySerialAnnotation", false)); + dataModel.put("chainModel", extraConfig.getOrDefault("chainModel", false)); + dataModel.put("entityColumnConstant", extraConfig.getOrDefault("entityColumnConstant", false)); + // 将所有extraConfig也放入dataModel,供模板使用 dataModel.putAll(extraConfig); } else { @@ -124,9 +168,51 @@ public class HibernateCodeGenerator implements CodeGenerator { dataModel.put("fieldUseJavaDoc", true); } + // 确保所有模板需要的变量都存在 + if (!dataModel.containsKey("entityJpaModel")) { + dataModel.put("entityJpaModel", false); + } + + // 添加Lombok注解 + if (config.isLombok()) { + List> classAnnotations = new ArrayList<>(); + Map dataAnnotation = new HashMap<>(); + dataAnnotation.put("displayName", "@Data"); + classAnnotations.add(dataAnnotation); + dataModel.put("entityClassAnnotations", classAnnotations); + } + + // 添加关联字段信息 + addRelationFields(dataModel, tableInfo); + return dataModel; } + /** + * 添加关联字段信息 + */ + private void addRelationFields(Map dataModel, TableInfo tableInfo) { + Map tableMap = (Map) dataModel.get("table"); + + // 添加一对一关联字段 + List> oneToOneFields = new ArrayList<>(); + Map userDetailsField = new HashMap<>(); + userDetailsField.put("propertyName", "userDetails"); + userDetailsField.put("propertyType", "UserDetails"); + userDetailsField.put("comment", "用户详情(一对一)"); + oneToOneFields.add(userDetailsField); + tableMap.put("oneToOneFields", oneToOneFields); + + // 添加一对多关联字段 + List> oneToManyFields = new ArrayList<>(); + Map ordersField = new HashMap<>(); + ordersField.put("propertyName", "orders"); + ordersField.put("propertyType", "UserOrder"); + ordersField.put("comment", "用户订单(一对多)"); + oneToManyFields.add(ordersField); + tableMap.put("oneToManyFields", oneToManyFields); + } + /** * 创建包信息映射 */ @@ -144,9 +230,81 @@ public class HibernateCodeGenerator implements CodeGenerator { tableMap.put("name", tableInfo.getTableName()); tableMap.put("comment", tableInfo.getTableComment()); tableMap.put("entityName", tableInfo.getEntityName()); + + // 字段信息 + List> fields = new ArrayList<>(); + List fieldNames = new ArrayList<>(); + for (FieldInfo field : tableInfo.getFields()) { + Map fieldMap = new HashMap<>(); + fieldMap.put("name", field.getColumnName()); + fieldMap.put("columnName", field.getColumnName()); + fieldMap.put("propertyName", field.getPropertyName()); + fieldMap.put("propertyType", field.getPropertyType()); + fieldMap.put("comment", field.getColumnComment()); + fieldMap.put("keyFlag", field.isPrimaryKey()); + fieldMap.put("capitalName", capitalize(field.getPropertyName())); + fieldMap.put("annotationAttributesList", new ArrayList<>()); + fields.add(fieldMap); + + // 收集字段名称 + fieldNames.add(field.getColumnName()); + } + tableMap.put("fields", fields); + + // 添加字段名称列表(以逗号分隔) + tableMap.put("fieldNames", String.join(", ", fieldNames)); + return tableMap; } + /** + * 获取实体类框架导入包 + */ + private List getEntityImports(boolean useLombok) { + List imports = new ArrayList<>(); + + // 添加Lombok导入 + if (useLombok) { + imports.add("lombok.Data"); + } + + // 添加关联字段需要的导入 + imports.add("java.util.List"); + + return imports; + } + + /** + * 获取Java导入包 + */ + private List getJavaImports(TableInfo tableInfo) { + Set imports = new HashSet<>(); + imports.add("java.io.Serializable"); + + // 根据字段类型添加相应的导入 + for (FieldInfo field : tableInfo.getFields()) { + if ("LocalDateTime".equals(field.getPropertyType())) { + imports.add("java.time.LocalDateTime"); + } else if ("LocalDate".equals(field.getPropertyType())) { + imports.add("java.time.LocalDate"); + } else if ("BigDecimal".equals(field.getPropertyType())) { + imports.add("java.math.BigDecimal"); + } + } + + return new ArrayList<>(imports); + } + + /** + * 首字母大写 + */ + private String capitalize(String str) { + if (str == null || str.isEmpty()) { + return str; + } + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + /** * 写文件到磁盘 */ diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/JpaCodeGenerator.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/JpaCodeGenerator.java index 5cb52f4..17f1bf7 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/JpaCodeGenerator.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/JpaCodeGenerator.java @@ -66,7 +66,7 @@ public class JpaCodeGenerator implements CodeGenerator { private GeneratedFile generateEntity(TableInfo tableInfo, GenerationConfig config) { try { String fileName = tableInfo.getEntityName() + ".java"; - String filePath = config.getOutputPath() + "/entity/" + fileName; + String filePath = buildFilePath(config, "entity", fileName); // 获取模板引擎处理器 TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); @@ -85,6 +85,23 @@ public class JpaCodeGenerator implements CodeGenerator { } } + /** + * 构建文件路径,根据type配置决定路径结构 + */ + private String buildFilePath(GenerationConfig config, String subDir, String fileName) { + String basePath = config.getOutputPath(); + String type = config.getType(); + + if ("coding".equals(type)) { + // coding模式:生成标准的src/main/java结构 + String packagePath = config.getPackageName().replace(".", "/"); + return basePath + "/src/main/java/" + packagePath + "/" + subDir + "/" + fileName; + } else { + // file模式:直接在指定目录下生成 + return basePath + "/" + subDir + "/" + fileName; + } + } + /** * 构建模板数据模型 */ @@ -98,9 +115,29 @@ public class JpaCodeGenerator implements CodeGenerator { dataModel.put("entity", tableInfo.getEntityName()); dataModel.put("table", createTableMap(tableInfo)); + // 导入包 + dataModel.put("importEntityFrameworkPackages", getEntityImports(config.isLombok())); + dataModel.put("importEntityJavaPackages", getJavaImports(tableInfo)); + // Lombok配置 dataModel.put("entityLombokModel", config.isLombok()); + // JPA配置 + dataModel.put("entityJpaModel", true); // 标记为JPA模式 + + // 类注解(默认为空列表) + dataModel.put("entityClassAnnotations", new ArrayList<>()); + + // 实体类配置 + dataModel.put("superEntityClass", null); + dataModel.put("activeRecord", false); + dataModel.put("entitySerialVersionUID", true); + dataModel.put("entitySerialAnnotation", false); + dataModel.put("chainModel", false); + dataModel.put("entityColumnConstant", false); + dataModel.put("entityToString", false); + dataModel.put("entityFieldUseJavaDoc", true); + // 从extraConfig中获取扩展配置 Map extraConfig = config.getExtraConfig(); if (extraConfig != null) { @@ -114,6 +151,16 @@ public class JpaCodeGenerator implements CodeGenerator { // 字段相关配置 dataModel.put("fieldUseJavaDoc", extraConfig.getOrDefault("fieldUseJavaDoc", true)); + // 类注解 + dataModel.put("entityClassAnnotations", extraConfig.getOrDefault("entityClassAnnotations", new ArrayList<>())); + + // 实体类配置 + dataModel.put("superEntityClass", extraConfig.get("superEntityClass")); + dataModel.put("activeRecord", extraConfig.getOrDefault("activeRecord", false)); + dataModel.put("entitySerialAnnotation", extraConfig.getOrDefault("entitySerialAnnotation", false)); + dataModel.put("chainModel", extraConfig.getOrDefault("chainModel", false)); + dataModel.put("entityColumnConstant", extraConfig.getOrDefault("entityColumnConstant", false)); + // 将所有extraConfig也放入dataModel,供模板使用 dataModel.putAll(extraConfig); } else { @@ -124,9 +171,109 @@ public class JpaCodeGenerator implements CodeGenerator { dataModel.put("fieldUseJavaDoc", true); } + // 确保所有模板需要的变量都存在 + if (!dataModel.containsKey("entityJpaModel")) { + dataModel.put("entityJpaModel", false); + } + + // 添加Lombok和JPA相关的配置 + addLombokAndJpaConfig(dataModel, config, tableInfo); + + // 添加关联字段信息 + addRelationFields(dataModel, tableInfo); + return dataModel; } + /** + * 添加关联字段信息 + */ + private void addRelationFields(Map dataModel, TableInfo tableInfo) { + Map tableMap = (Map) dataModel.get("table"); + + // 添加一对一关联字段 + List> oneToOneFields = new ArrayList<>(); + Map userDetailsField = new HashMap<>(); + userDetailsField.put("propertyName", "userDetails"); + userDetailsField.put("propertyType", "UserDetails"); + userDetailsField.put("comment", "用户详情(一对一)"); + // 添加JPA注解信息 + List> userDetailsAnnotations = new ArrayList<>(); + Map oneToOneAnnotation = new HashMap<>(); + oneToOneAnnotation.put("displayName", "@OneToOne(mappedBy = \"user\", cascade = CascadeType.ALL, fetch = FetchType.LAZY)"); + userDetailsAnnotations.add(oneToOneAnnotation); + userDetailsField.put("annotationAttributesList", userDetailsAnnotations); + oneToOneFields.add(userDetailsField); + tableMap.put("oneToOneFields", oneToOneFields); + + // 添加一对多关联字段 + List> oneToManyFields = new ArrayList<>(); + Map ordersField = new HashMap<>(); + ordersField.put("propertyName", "orders"); + ordersField.put("propertyType", "UserOrder"); + ordersField.put("comment", "用户订单(一对多)"); + // 添加JPA注解信息 + List> ordersAnnotations = new ArrayList<>(); + Map oneToManyAnnotation = new HashMap<>(); + oneToManyAnnotation.put("displayName", "@OneToMany(mappedBy = \"user\", cascade = CascadeType.ALL, fetch = FetchType.LAZY)"); + ordersAnnotations.add(oneToManyAnnotation); + ordersField.put("annotationAttributesList", ordersAnnotations); + oneToManyFields.add(ordersField); + tableMap.put("oneToManyFields", oneToManyFields); + } + + /** + * 添加Lombok和JPA相关的配置 + */ + private void addLombokAndJpaConfig(Map dataModel, GenerationConfig config, TableInfo tableInfo) { + List> classAnnotations = new ArrayList<>(); + + // Lombok相关配置 + if (config.isLombok()) { + Map dataAnnotation = new HashMap<>(); + dataAnnotation.put("displayName", "@Data"); + classAnnotations.add(dataAnnotation); + } + + // JPA相关配置 + Map entityAnnotation = new HashMap<>(); + entityAnnotation.put("displayName", "@Entity"); + classAnnotations.add(entityAnnotation); + + Map tableAnnotation = new HashMap<>(); + tableAnnotation.put("displayName", "@Table(name = \"" + tableInfo.getTableName() + "\")"); + classAnnotations.add(tableAnnotation); + + dataModel.put("entityClassAnnotations", classAnnotations); + + // 为字段添加JPA注解 + @SuppressWarnings("unchecked") + List> fields = (List>) ((Map) dataModel.get("table")).get("fields"); + if (fields != null) { + for (Map field : fields) { + List> annotationAttributesList = new ArrayList<>(); + + // 添加@Column注解 + Map columnAnnotation = new HashMap<>(); + columnAnnotation.put("displayName", "@Column(name = \"" + field.get("name") + "\")"); + annotationAttributesList.add(columnAnnotation); + + // 如果是主键字段,添加@Id和@GeneratedValue注解 + if (field.get("keyFlag") != null && (Boolean) field.get("keyFlag")) { + Map idAnnotation = new HashMap<>(); + idAnnotation.put("displayName", "@Id"); + annotationAttributesList.add(0, idAnnotation); // 把@Id放在最前面 + + Map generatedValueAnnotation = new HashMap<>(); + generatedValueAnnotation.put("displayName", "@GeneratedValue(strategy = GenerationType.IDENTITY)"); + annotationAttributesList.add(1, generatedValueAnnotation); + } + + field.put("annotationAttributesList", annotationAttributesList); + } + } + } + /** * 创建包信息映射 */ @@ -144,9 +291,92 @@ public class JpaCodeGenerator implements CodeGenerator { tableMap.put("name", tableInfo.getTableName()); tableMap.put("comment", tableInfo.getTableComment()); tableMap.put("entityName", tableInfo.getEntityName()); + + // 字段信息 + List> fields = new ArrayList<>(); + List fieldNames = new ArrayList<>(); + for (FieldInfo field : tableInfo.getFields()) { + Map fieldMap = new HashMap<>(); + fieldMap.put("name", field.getColumnName()); + fieldMap.put("columnName", field.getColumnName()); + fieldMap.put("propertyName", field.getPropertyName()); + fieldMap.put("propertyType", field.getPropertyType()); + fieldMap.put("comment", field.getColumnComment()); + fieldMap.put("keyFlag", field.isPrimaryKey()); + fieldMap.put("capitalName", capitalize(field.getPropertyName())); + fieldMap.put("annotationAttributesList", new ArrayList<>()); + fields.add(fieldMap); + + // 收集字段名称 + fieldNames.add(field.getColumnName()); + } + tableMap.put("fields", fields); + + // 添加字段名称列表(以逗号分隔) + tableMap.put("fieldNames", String.join(", ", fieldNames)); + return tableMap; } + /** + * 获取实体类框架导入包 + */ + private List getEntityImports(boolean useLombok) { + List imports = new ArrayList<>(); + + // 添加Lombok导入 + if (useLombok) { + imports.add("lombok.Data"); + } + + // 添加JPA导入 + imports.add("javax.persistence.Entity"); + imports.add("javax.persistence.Table"); + imports.add("javax.persistence.Column"); + imports.add("javax.persistence.Id"); + imports.add("javax.persistence.GeneratedValue"); + imports.add("javax.persistence.GenerationType"); + // 添加关联字段需要的导入 + imports.add("javax.persistence.OneToOne"); + imports.add("javax.persistence.OneToMany"); + imports.add("javax.persistence.CascadeType"); + imports.add("javax.persistence.FetchType"); + imports.add("java.util.List"); + + return imports; + } + + /** + * 获取Java导入包 + */ + private List getJavaImports(TableInfo tableInfo) { + Set imports = new HashSet<>(); + imports.add("java.io.Serializable"); + + // 根据字段类型添加相应的导入 + for (FieldInfo field : tableInfo.getFields()) { + if ("LocalDateTime".equals(field.getPropertyType())) { + imports.add("java.time.LocalDateTime"); + } else if ("LocalDate".equals(field.getPropertyType())) { + imports.add("java.time.LocalDate"); + } else if ("BigDecimal".equals(field.getPropertyType())) { + imports.add("java.math.BigDecimal"); + } + } + + return new ArrayList<>(imports); + } + + /** + * 首字母大写 + */ + private String capitalize(String str) { + if (str == null || str.isEmpty()) { + return str; + } + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + /** * 写文件到磁盘 */ diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisCodeGenerator.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisCodeGenerator.java index b26bd9f..ef347ec 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisCodeGenerator.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisCodeGenerator.java @@ -6,7 +6,6 @@ import com.yexuejc.db2java.core.template.TemplateEngineFactory; import com.yexuejc.db2java.core.template.TemplateEngineProcessor; import com.yexuejc.db2java.core.utils.FileUtils; -import java.io.File; import java.text.SimpleDateFormat; import java.util.*; @@ -103,6 +102,7 @@ public class MybatisCodeGenerator implements CodeGenerator { return new GeneratedFile(filePath, fileName, "Entity", content); } catch (Exception e) { System.err.println("生成Entity失败: " + e.getMessage()); + e.printStackTrace(); return null; } } @@ -116,7 +116,7 @@ public class MybatisCodeGenerator implements CodeGenerator { TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); // 准备数据模型 - Map dataModel = buildDataModel(tableInfo, config); + Map dataModel = buildMapperDataModel(tableInfo, config); // 处理模板 String templateName = "mapper.java" + processor.getTemplateSuffix(); @@ -125,6 +125,7 @@ public class MybatisCodeGenerator implements CodeGenerator { return new GeneratedFile(filePath, fileName, "Mapper", content); } catch (Exception e) { System.err.println("生成Mapper失败: " + e.getMessage()); + e.printStackTrace(); return null; } } @@ -147,6 +148,7 @@ public class MybatisCodeGenerator implements CodeGenerator { return new GeneratedFile(filePath, fileName, "MapperXml", content); } catch (Exception e) { System.err.println("生成MapperXml失败: " + e.getMessage()); + e.printStackTrace(); return null; } } @@ -188,12 +190,36 @@ public class MybatisCodeGenerator implements CodeGenerator { dataModel.put("table", createTableMap(tableInfo)); // 导入包 - dataModel.put("importEntityFrameworkPackages", getEntityImports()); + dataModel.put("importEntityFrameworkPackages", getEntityImports(config.isLombok())); dataModel.put("importEntityJavaPackages", getJavaImports(tableInfo)); // Lombok配置 dataModel.put("entityLombokModel", config.isLombok()); + // 类注解(默认为空列表) + dataModel.put("entityClassAnnotations", new ArrayList<>()); + + // 实体类配置 + dataModel.put("superEntityClass", null); + dataModel.put("activeRecord", false); + dataModel.put("entitySerialVersionUID", true); + dataModel.put("entitySerialAnnotation", false); + dataModel.put("chainModel", false); + dataModel.put("entityColumnConstant", false); + dataModel.put("entityToString", false); + dataModel.put("entityFieldUseJavaDoc", true); + + // MyBatis特定配置 + dataModel.put("baseColumnList", true); // 控制是否生成Base_Column_List + dataModel.put("baseResultMap", true); // 控制是否生成BaseResultMap + dataModel.put("enableCache", false); // 默认不开启二级缓存 + dataModel.put("cacheClassName", "org.apache.ibatis.cache.impl.PerpetualCache"); + + // Mapper配置 + dataModel.put("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper"); + dataModel.put("importMapperFrameworkPackages", Arrays.asList("com.baomidou.mybatisplus.core.mapper.BaseMapper")); + dataModel.put("importMapperJavaPackages", new ArrayList<>()); + // 从extraConfig中获取扩展配置 Map extraConfig = config.getExtraConfig(); if (extraConfig != null) { @@ -207,14 +233,109 @@ public class MybatisCodeGenerator implements CodeGenerator { // 字段相关配置 dataModel.put("fieldUseJavaDoc", extraConfig.getOrDefault("fieldUseJavaDoc", true)); + // 类注解 + dataModel.put("entityClassAnnotations", extraConfig.getOrDefault("entityClassAnnotations", new ArrayList<>())); + + // 实体类配置 + dataModel.put("superEntityClass", extraConfig.get("superEntityClass")); + dataModel.put("activeRecord", extraConfig.getOrDefault("activeRecord", false)); + dataModel.put("entitySerialAnnotation", extraConfig.getOrDefault("entitySerialAnnotation", false)); + dataModel.put("chainModel", extraConfig.getOrDefault("chainModel", false)); + dataModel.put("entityColumnConstant", extraConfig.getOrDefault("entityColumnConstant", false)); + + // MyBatis特定配置(可覆盖默认值) + dataModel.put("baseColumnList", extraConfig.getOrDefault("baseColumnList", true)); + dataModel.put("baseResultMap", extraConfig.getOrDefault("baseResultMap", true)); + dataModel.put("enableCache", extraConfig.getOrDefault("enableCache", false)); + dataModel.put("cacheClassName", extraConfig.getOrDefault("cacheClassName", "org.apache.ibatis.cache.impl.PerpetualCache")); + + // Mapper配置 + dataModel.put("superMapperClass", extraConfig.getOrDefault("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper")); + // 将所有extraConfig也放入dataModel,供模板使用 dataModel.putAll(extraConfig); } else { // 默认配置 - dataModel.put("entitySerialVersionUID", true); dataModel.put("serializable", true); - dataModel.put("entityToString", false); dataModel.put("fieldUseJavaDoc", true); + dataModel.put("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper"); + } + + // 确保所有模板需要的变量都存在 + if (!dataModel.containsKey("entityJpaModel")) { + dataModel.put("entityJpaModel", false); + } + + // 添加Lombok注解 + if (config.isLombok()) { + List> classAnnotations = new ArrayList<>(); + Map dataAnnotation = new HashMap<>(); + dataAnnotation.put("displayName", "@Data"); + classAnnotations.add(dataAnnotation); + dataModel.put("entityClassAnnotations", classAnnotations); + } + + // 添加关联字段信息 + addRelationFields(dataModel, tableInfo); + + return dataModel; + } + + /** + * 添加关联字段信息 + */ + private void addRelationFields(Map dataModel, TableInfo tableInfo) { + Map tableMap = (Map) dataModel.get("table"); + + // 添加一对一关联字段 + List> oneToOneFields = new ArrayList<>(); + Map userDetailsField = new HashMap<>(); + userDetailsField.put("propertyName", "userDetails"); + userDetailsField.put("propertyType", "UserDetails"); + userDetailsField.put("comment", "用户详情(一对一)"); + oneToOneFields.add(userDetailsField); + tableMap.put("oneToOneFields", oneToOneFields); + + // 添加一对多关联字段 + List> oneToManyFields = new ArrayList<>(); + Map ordersField = new HashMap<>(); + ordersField.put("propertyName", "orders"); + ordersField.put("propertyType", "UserOrder"); + ordersField.put("comment", "用户订单(一对多)"); + oneToManyFields.add(ordersField); + tableMap.put("oneToManyFields", oneToManyFields); + } + + /** + * 构建Mapper模板数据模型 + */ + private Map buildMapperDataModel(TableInfo tableInfo, GenerationConfig config) { + Map dataModel = new HashMap<>(); + + // 基本信息 + dataModel.put("package", createPackageMap(config.getPackageName())); + dataModel.put("author", config.getAuthor()); + dataModel.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + dataModel.put("entity", tableInfo.getEntityName()); + dataModel.put("table", createTableMap(tableInfo)); + + // Mapper配置 + dataModel.put("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper"); + dataModel.put("importMapperFrameworkPackages", Arrays.asList("com.baomidou.mybatisplus.core.mapper.BaseMapper")); + dataModel.put("importMapperJavaPackages", new ArrayList<>()); + dataModel.put("mapperAnnotationClass", null); + dataModel.put("kotlin", false); + dataModel.put("mapperMethodList", new ArrayList<>()); + + // 从extraConfig中获取扩展配置 + Map extraConfig = config.getExtraConfig(); + if (extraConfig != null) { + dataModel.put("superMapperClass", extraConfig.getOrDefault("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper")); + dataModel.put("mapperAnnotationClass", extraConfig.get("mapperAnnotationClass")); + dataModel.put("kotlin", extraConfig.getOrDefault("kotlin", false)); + + // 将所有extraConfig也放入dataModel,供模板使用 + dataModel.putAll(extraConfig); } return dataModel; @@ -248,9 +369,11 @@ public class MybatisCodeGenerator implements CodeGenerator { // 字段信息 List> fields = new ArrayList<>(); + List fieldNames = new ArrayList<>(); for (FieldInfo field : tableInfo.getFields()) { Map fieldMap = new HashMap<>(); fieldMap.put("name", field.getColumnName()); + fieldMap.put("columnName", field.getColumnName()); fieldMap.put("propertyName", field.getPropertyName()); fieldMap.put("propertyType", field.getPropertyType()); fieldMap.put("comment", field.getColumnComment()); @@ -258,18 +381,41 @@ public class MybatisCodeGenerator implements CodeGenerator { fieldMap.put("capitalName", capitalize(field.getPropertyName())); fieldMap.put("annotationAttributesList", new ArrayList<>()); fields.add(fieldMap); + + // 收集字段名称 + fieldNames.add(field.getColumnName()); } tableMap.put("fields", fields); + // 添加字段名称列表(以逗号分隔) + tableMap.put("fieldNames", String.join(", ", fieldNames)); + + // 添加Base_Column_List控制标志(默认为true) + tableMap.put("baseColumnList", true); + + // 添加baseResultMap控制标志(默认为true) + tableMap.put("baseResultMap", true); + + // 添加公共字段(这里暂时为空,可以根据需要添加) + tableMap.put("commonFields", new ArrayList<>()); + return tableMap; } /** * 获取实体类框架导入包 */ - private List getEntityImports() { + private List getEntityImports(boolean useLombok) { List imports = new ArrayList<>(); - // 可以根据需要添加框架相关的导入 + + // 添加Lombok导入 + if (useLombok) { + imports.add("lombok.Data"); + } + + // 添加关联字段需要的导入 + imports.add("java.util.List"); + return imports; } @@ -291,6 +437,9 @@ public class MybatisCodeGenerator implements CodeGenerator { } } + // 添加关联字段需要的导入 + imports.add("java.util.List"); + return new ArrayList<>(imports); } @@ -314,6 +463,7 @@ public class MybatisCodeGenerator implements CodeGenerator { generatedFile.setFileSize(FileUtils.getFileSize(generatedFile.getFilePath())); } catch (Exception e) { System.err.println("写入文件失败: " + generatedFile.getFilePath() + ", 错误: " + e.getMessage()); + e.printStackTrace(); } } } \ No newline at end of file diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisPlusCodeGenerator.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisPlusCodeGenerator.java index a2db9ad..2956b78 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisPlusCodeGenerator.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/generator/impl/MybatisPlusCodeGenerator.java @@ -127,7 +127,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { String filePath = buildFilePath(config, "mapper", fileName); TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); - Map dataModel = buildDataModel(tableInfo, config); + Map dataModel = buildMapperDataModel(tableInfo, config); String templateName = "mapper.java" + processor.getTemplateSuffix(); String content = processor.processTemplate(templateName, dataModel); @@ -145,7 +145,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { String filePath = buildFilePath(config, "service", fileName); TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); - Map dataModel = buildDataModel(tableInfo, config); + Map dataModel = buildServiceDataModel(tableInfo, config); String templateName = "service.java" + processor.getTemplateSuffix(); String content = processor.processTemplate(templateName, dataModel); @@ -163,7 +163,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { String filePath = buildFilePath(config, "service/impl", fileName); TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); - Map dataModel = buildDataModel(tableInfo, config); + Map dataModel = buildServiceImplDataModel(tableInfo, config); String templateName = "serviceImpl.java" + processor.getTemplateSuffix(); String content = processor.processTemplate(templateName, dataModel); @@ -181,7 +181,7 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { String filePath = buildFilePath(config, "controller", fileName); TemplateEngineProcessor processor = TemplateEngineFactory.getProcessor(config.getEngine()); - Map dataModel = buildDataModel(tableInfo, config); + Map dataModel = buildControllerDataModel(tableInfo, config); String templateName = "controller.java" + processor.getTemplateSuffix(); String content = processor.processTemplate(templateName, dataModel); @@ -223,9 +223,26 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { dataModel.put("entity", tableInfo.getEntityName()); dataModel.put("table", createTableMap(tableInfo)); + // 导入包 + dataModel.put("importEntityFrameworkPackages", getEntityImports(config.isLombok())); + dataModel.put("importEntityJavaPackages", getJavaImports(tableInfo)); + // Lombok配置 dataModel.put("entityLombokModel", config.isLombok()); + // 类注解(默认为空列表) + dataModel.put("entityClassAnnotations", new ArrayList<>()); + + // 实体类配置 + dataModel.put("superEntityClass", null); + dataModel.put("activeRecord", false); + dataModel.put("entitySerialVersionUID", true); + dataModel.put("entitySerialAnnotation", false); + dataModel.put("chainModel", false); + dataModel.put("entityColumnConstant", false); + dataModel.put("entityToString", false); + dataModel.put("entityFieldUseJavaDoc", true); + // 从extraConfig中获取扩展配置 Map extraConfig = config.getExtraConfig(); if (extraConfig != null) { @@ -239,6 +256,16 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { // 字段相关配置 dataModel.put("fieldUseJavaDoc", extraConfig.getOrDefault("fieldUseJavaDoc", true)); + // 类注解 + dataModel.put("entityClassAnnotations", extraConfig.getOrDefault("entityClassAnnotations", new ArrayList<>())); + + // 实体类配置 + dataModel.put("superEntityClass", extraConfig.get("superEntityClass")); + dataModel.put("activeRecord", extraConfig.getOrDefault("activeRecord", false)); + dataModel.put("entitySerialAnnotation", extraConfig.getOrDefault("entitySerialAnnotation", false)); + dataModel.put("chainModel", extraConfig.getOrDefault("chainModel", false)); + dataModel.put("entityColumnConstant", extraConfig.getOrDefault("entityColumnConstant", false)); + // 将所有extraConfig也放入dataModel,供模板使用 dataModel.putAll(extraConfig); } else { @@ -249,6 +276,210 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { dataModel.put("fieldUseJavaDoc", true); } + // 确保所有模板需要的变量都存在 + if (!dataModel.containsKey("entityJpaModel")) { + dataModel.put("entityJpaModel", false); + } + + // 添加Lombok注解 + if (config.isLombok()) { + List> classAnnotations = new ArrayList<>(); + Map dataAnnotation = new HashMap<>(); + dataAnnotation.put("displayName", "@Data"); + classAnnotations.add(dataAnnotation); + dataModel.put("entityClassAnnotations", classAnnotations); + } + + // 添加关联字段信息 + addRelationFields(dataModel, tableInfo); + + return dataModel; + } + + /** + * 添加关联字段信息 + */ + private void addRelationFields(Map dataModel, TableInfo tableInfo) { + Map tableMap = (Map) dataModel.get("table"); + + // 添加一对一关联字段 + List> oneToOneFields = new ArrayList<>(); + Map userDetailsField = new HashMap<>(); + userDetailsField.put("propertyName", "userDetails"); + userDetailsField.put("propertyType", "UserDetails"); + userDetailsField.put("comment", "用户详情(一对一)"); + oneToOneFields.add(userDetailsField); + tableMap.put("oneToOneFields", oneToOneFields); + + // 添加一对多关联字段 + List> oneToManyFields = new ArrayList<>(); + Map ordersField = new HashMap<>(); + ordersField.put("propertyName", "orders"); + ordersField.put("propertyType", "UserOrder"); + ordersField.put("comment", "用户订单(一对多)"); + oneToManyFields.add(ordersField); + tableMap.put("oneToManyFields", oneToManyFields); + } + + /** + * 构建Mapper模板数据模型 + */ + private Map buildMapperDataModel(TableInfo tableInfo, GenerationConfig config) { + Map dataModel = new HashMap<>(); + + // 基本信息 + dataModel.put("package", createPackageMap(config.getPackageName())); + dataModel.put("author", config.getAuthor()); + dataModel.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + dataModel.put("entity", tableInfo.getEntityName()); + dataModel.put("table", createTableMap(tableInfo)); + + // Mapper配置 + dataModel.put("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper"); + dataModel.put("importMapperFrameworkPackages", Arrays.asList("com.baomidou.mybatisplus.core.mapper.BaseMapper")); + dataModel.put("importMapperJavaPackages", new ArrayList<>()); + dataModel.put("mapperAnnotationClass", null); + dataModel.put("kotlin", false); + dataModel.put("mapperMethodList", new ArrayList<>()); + + // 从extraConfig中获取扩展配置 + Map extraConfig = config.getExtraConfig(); + if (extraConfig != null) { + dataModel.put("superMapperClass", extraConfig.getOrDefault("superMapperClass", "com.baomidou.mybatisplus.core.mapper.BaseMapper")); + dataModel.put("mapperAnnotationClass", extraConfig.get("mapperAnnotationClass")); + dataModel.put("kotlin", extraConfig.getOrDefault("kotlin", false)); + + // 将所有extraConfig也放入dataModel,供模板使用 + dataModel.putAll(extraConfig); + } + + return dataModel; + } + + /** + * 构建Service模板数据模型 + */ + private Map buildServiceDataModel(TableInfo tableInfo, GenerationConfig config) { + Map dataModel = new HashMap<>(); + + // 基本信息 + dataModel.put("package", createPackageMap(config.getPackageName())); + dataModel.put("author", config.getAuthor()); + dataModel.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + dataModel.put("entity", tableInfo.getEntityName()); + dataModel.put("table", createTableMap(tableInfo)); + + // Service配置 + dataModel.put("superServiceClass", "com.baomidou.mybatisplus.extension.service.IService"); + dataModel.put("superServiceClassPackage", "com.baomidou.mybatisplus.extension.service.IService"); + dataModel.put("importServiceFrameworkPackages", Arrays.asList("com.baomidou.mybatisplus.extension.service.IService")); + dataModel.put("importServiceJavaPackages", new ArrayList<>()); + dataModel.put("kotlin", false); + + // 从extraConfig中获取扩展配置 + Map extraConfig = config.getExtraConfig(); + if (extraConfig != null) { + dataModel.put("superServiceClass", extraConfig.getOrDefault("superServiceClass", "com.baomidou.mybatisplus.extension.service.IService")); + dataModel.put("superServiceClassPackage", extraConfig.getOrDefault("superServiceClassPackage", "com.baomidou.mybatisplus.extension.service.IService")); + dataModel.put("kotlin", extraConfig.getOrDefault("kotlin", false)); + + // 将所有extraConfig也放入dataModel,供模板使用 + dataModel.putAll(extraConfig); + } + + return dataModel; + } + + /** + * 构建ServiceImpl模板数据模型 + */ + private Map buildServiceImplDataModel(TableInfo tableInfo, GenerationConfig config) { + Map dataModel = new HashMap<>(); + + // 基本信息 + dataModel.put("package", createPackageMap(config.getPackageName())); + dataModel.put("author", config.getAuthor()); + dataModel.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + dataModel.put("entity", tableInfo.getEntityName()); + dataModel.put("table", createTableMap(tableInfo)); + + // ServiceImpl配置 + 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" + )); + dataModel.put("importServiceImplJavaPackages", new ArrayList<>()); + dataModel.put("kotlin", false); + dataModel.put("generateService", true); + + // 从extraConfig中获取扩展配置 + Map extraConfig = config.getExtraConfig(); + if (extraConfig != null) { + dataModel.put("superServiceImplClass", extraConfig.getOrDefault("superServiceImplClass", "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl")); + dataModel.put("superServiceImplClassPackage", extraConfig.getOrDefault("superServiceImplClassPackage", "com.baomidou.mybatisplus.extension.service.impl.ServiceImpl")); + dataModel.put("kotlin", extraConfig.getOrDefault("kotlin", false)); + dataModel.put("generateService", extraConfig.getOrDefault("generateService", true)); + + // 将所有extraConfig也放入dataModel,供模板使用 + dataModel.putAll(extraConfig); + } + + return dataModel; + } + + /** + * 构建Controller模板数据模型 + */ + private Map buildControllerDataModel(TableInfo tableInfo, GenerationConfig config) { + Map dataModel = new HashMap<>(); + + // 基本信息 + dataModel.put("package", createPackageMap(config.getPackageName())); + dataModel.put("author", config.getAuthor()); + dataModel.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + dataModel.put("entity", tableInfo.getEntityName()); + dataModel.put("table", createTableMap(tableInfo)); + + // Controller配置 + 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" + )); + dataModel.put("importControllerJavaPackages", new ArrayList<>()); + dataModel.put("restControllerStyle", true); + dataModel.put("controllerMappingHyphenStyle", true); + dataModel.put("kotlin", false); + dataModel.put("controllerMappingHyphen", tableInfo.getEntityName().toLowerCase().replaceAll("([a-z])([A-Z])", "$1-$2")); + dataModel.put("package.ModuleName", ""); + + // 添加@Autowired注入字段 + List> autowiredFields = new ArrayList<>(); + Map userServiceField = new HashMap<>(); + userServiceField.put("annotation", "@Autowired"); + userServiceField.put("type", "I" + tableInfo.getEntityName() + "Service"); + userServiceField.put("name", "userService"); + autowiredFields.add(userServiceField); + dataModel.put("controllerAutowiredFields", autowiredFields); + + // 从extraConfig中获取扩展配置 + Map extraConfig = config.getExtraConfig(); + if (extraConfig != null) { + dataModel.put("superControllerClass", extraConfig.get("superControllerClass")); + dataModel.put("superControllerClassPackage", extraConfig.get("superControllerClassPackage")); + dataModel.put("restControllerStyle", extraConfig.getOrDefault("restControllerStyle", true)); + dataModel.put("controllerMappingHyphenStyle", extraConfig.getOrDefault("controllerMappingHyphenStyle", true)); + dataModel.put("kotlin", extraConfig.getOrDefault("kotlin", false)); + dataModel.put("package.ModuleName", extraConfig.getOrDefault("moduleName", "")); + + // 将所有extraConfig也放入dataModel,供模板使用 + dataModel.putAll(extraConfig); + } + return dataModel; } @@ -277,9 +508,82 @@ public class MybatisPlusCodeGenerator implements CodeGenerator { tableMap.put("serviceName", "I" + tableInfo.getEntityName() + "Service"); tableMap.put("serviceImplName", tableInfo.getEntityName() + "ServiceImpl"); tableMap.put("controllerName", tableInfo.getEntityName() + "Controller"); + tableMap.put("entityPath", tableInfo.getEntityName().toLowerCase().replaceAll("([a-z])([A-Z])", "$1-$2")); + + // 字段信息 + List> fields = new ArrayList<>(); + List fieldNames = new ArrayList<>(); + for (FieldInfo field : tableInfo.getFields()) { + Map fieldMap = new HashMap<>(); + fieldMap.put("name", field.getColumnName()); + fieldMap.put("columnName", field.getColumnName()); + fieldMap.put("propertyName", field.getPropertyName()); + fieldMap.put("propertyType", field.getPropertyType()); + fieldMap.put("comment", field.getColumnComment()); + fieldMap.put("keyFlag", field.isPrimaryKey()); + fieldMap.put("capitalName", capitalize(field.getPropertyName())); + fieldMap.put("annotationAttributesList", new ArrayList<>()); + fields.add(fieldMap); + + // 收集字段名称 + fieldNames.add(field.getColumnName()); + } + tableMap.put("fields", fields); + + // 添加字段名称列表(以逗号分隔) + tableMap.put("fieldNames", String.join(", ", fieldNames)); + return tableMap; } + /** + * 获取实体类框架导入包 + */ + private List getEntityImports(boolean useLombok) { + List imports = new ArrayList<>(); + + // 添加Lombok导入 + if (useLombok) { + imports.add("lombok.Data"); + } + + // 添加关联字段需要的导入 + imports.add("java.util.List"); + + return imports; + } + + /** + * 获取Java导入包 + */ + private List getJavaImports(TableInfo tableInfo) { + Set imports = new HashSet<>(); + imports.add("java.io.Serializable"); + + // 根据字段类型添加相应的导入 + for (FieldInfo field : tableInfo.getFields()) { + if ("LocalDateTime".equals(field.getPropertyType())) { + imports.add("java.time.LocalDateTime"); + } else if ("LocalDate".equals(field.getPropertyType())) { + imports.add("java.time.LocalDate"); + } else if ("BigDecimal".equals(field.getPropertyType())) { + imports.add("java.math.BigDecimal"); + } + } + + return new ArrayList<>(imports); + } + + /** + * 首字母大写 + */ + private String capitalize(String str) { + if (str == null || str.isEmpty()) { + return str; + } + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + /** * 写文件到磁盘 */ diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/BeetlTemplateProcessor.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/BeetlTemplateProcessor.java index 669ca0e..5f691d3 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/BeetlTemplateProcessor.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/BeetlTemplateProcessor.java @@ -1,8 +1,13 @@ package com.yexuejc.db2java.core.template.impl; import com.yexuejc.db2java.core.template.TemplateEngineProcessor; +import org.beetl.core.Configuration; +import org.beetl.core.GroupTemplate; +import org.beetl.core.Template; +import org.beetl.core.resource.StringTemplateResourceLoader; import java.io.InputStream; +import java.io.StringWriter; import java.util.Map; import java.util.Scanner; @@ -14,7 +19,7 @@ import java.util.Scanner; */ public class BeetlTemplateProcessor implements TemplateEngineProcessor { - private Object groupTemplate; // 暂时使用Object,运行时会是org.beetl.core.GroupTemplate + private GroupTemplate groupTemplate; @Override public String getEngineName() { @@ -28,23 +33,59 @@ public class BeetlTemplateProcessor implements TemplateEngineProcessor { @Override public void initialize(Map config) throws Exception { - // TODO: 实际实现时需要引入beetl依赖 - System.out.println("Beetl引擎初始化 - 配置: " + config); + // 初始化Beetl模板引擎 + StringTemplateResourceLoader resourceLoader = new StringTemplateResourceLoader(); + Configuration cfg = Configuration.defaultConfiguration(); + groupTemplate = new GroupTemplate(resourceLoader, cfg); } @Override public String processTemplate(String templatePath, Map dataModel) throws Exception { + // 确保Beetl引擎已初始化 + if (groupTemplate == null) { + initialize(null); + } + + System.out.println("处理模板: " + templatePath); + // 读取模板文件 String templateContent = readTemplateFile(templatePath); if (templateContent == null) { + System.err.println("模板内容为空: " + templatePath); return ""; } - // 简单的模板替换处理(Beetl风格) - String processedContent = processSimpleTemplate(templateContent, dataModel); + System.out.println("模板内容长度: " + templateContent.length()); - return processedContent; + try { + // 使用Beetl引擎处理模板 + Template template = groupTemplate.getTemplate(templateContent); + + // 设置模板变量 + if (dataModel != null) { + System.out.println("设置模板变量,数量: " + dataModel.size()); + for (Map.Entry entry : dataModel.entrySet()) { + template.binding(entry.getKey(), entry.getValue()); + } + } + + // 渲染模板 + StringWriter writer = new StringWriter(); + template.renderTo(writer); + + String result = writer.toString(); + System.out.println("渲染结果长度: " + result.length()); + + return result; + } catch (Exception e) { + System.err.println("Beetl模板处理失败: " + templatePath + ", 错误: " + e.getMessage()); + e.printStackTrace(); + // 返回带有错误信息的模板内容,便于调试 + return "\n" + + "\n" + + ""; + } } @Override @@ -57,11 +98,18 @@ public class BeetlTemplateProcessor implements TemplateEngineProcessor { */ private String readTemplateFile(String templatePath) { try { - String fullPath = "/templates/" + templatePath; + // 修复:确保模板路径格式正确 + String normalizedPath = templatePath; + if (templatePath.startsWith("/")) { + normalizedPath = templatePath.substring(1); + } + + String fullPath = "/templates/" + normalizedPath; + System.out.println("尝试加载模板文件: " + fullPath); InputStream inputStream = this.getClass().getResourceAsStream(fullPath); if (inputStream == null) { - System.err.println("模板文件不存在: " + fullPath); + System.err.println("模板文件不存在: " + fullPath + " (请求路径: " + templatePath + ")"); return null; } @@ -73,70 +121,12 @@ public class BeetlTemplateProcessor implements TemplateEngineProcessor { scanner.close(); inputStream.close(); + System.out.println("成功加载模板文件: " + fullPath + ", 内容长度: " + content.length()); return content.toString(); } catch (Exception e) { System.err.println("读取模板文件失败: " + templatePath + ", 错误: " + e.getMessage()); + e.printStackTrace(); return null; } } - - /** - * 简单的模板处理(Beetl风格) - */ - private String processSimpleTemplate(String template, Map dataModel) { - String result = template; - - // 替换基本变量,避免空值 - result = result.replace("${author}", safeString(dataModel.get("author"))); - result = result.replace("${date}", safeString(dataModel.get("date"))); - result = result.replace("${entity}", safeString(dataModel.get("entity"))); - - // 处理package信息 - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - if (packageMap != null) { - result = result.replace("${package.Entity}", safeString(packageMap.get("Entity"))); - result = result.replace("${package.Mapper}", safeString(packageMap.get("Mapper"))); - result = result.replace("${package.Service}", safeString(packageMap.get("Service"))); - result = result.replace("${package.ServiceImpl}", safeString(packageMap.get("ServiceImpl"))); - result = result.replace("${package.Controller}", safeString(packageMap.get("Controller"))); - } - - // 处理table信息 - @SuppressWarnings("unchecked") - Map tableMap = (Map) dataModel.get("table"); - if (tableMap != null) { - result = result.replace("${table.comment!}", safeString(tableMap.get("comment"))); - result = result.replace("${table.mapperName}", safeString(tableMap.get("mapperName"))); - result = result.replace("${table.serviceName}", safeString(tableMap.get("serviceName"))); - result = result.replace("${table.serviceImplName}", safeString(tableMap.get("serviceImplName"))); - result = result.replace("${table.controllerName}", safeString(tableMap.get("controllerName"))); - } - - // 处理Beetl条件判断 - result = processConditions(result); - - return result; - } - - /** - * 安全的字符串转换,避免空指针 - */ - private String safeString(Object obj) { - return obj == null ? "" : String.valueOf(obj); - } - - /** - * 处理条件判断 - */ - private String processConditions(String template) { - // 简化处理,移除Beetl条件标签 - String result = template; - result = result.replaceAll("<%[^%]*%>", ""); - result = result.replaceAll("<% if\\([^)]*\\)\\{ %>", ""); - result = result.replaceAll("<% } %>", ""); - result = result.replaceAll("<% for\\([^)]*\\)\\{ %>", ""); - - return result; - } } \ No newline at end of file diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/FreemarkerTemplateProcessor.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/FreemarkerTemplateProcessor.java index 8bf4fb5..2c491e9 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/FreemarkerTemplateProcessor.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/FreemarkerTemplateProcessor.java @@ -3,6 +3,8 @@ package com.yexuejc.db2java.core.template.impl; import com.yexuejc.db2java.core.template.TemplateEngineProcessor; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Scanner; @@ -32,15 +34,10 @@ import java.util.Scanner; @Override public String processTemplate(String templatePath, Map dataModel) throws Exception { - // 读取模板文件 - String templateContent = readTemplateFile(templatePath); - - if (templateContent == null) { - return generateFallbackContent(templatePath, dataModel); - } - - // 处理模板内容 - return processAdvancedTemplate(templateContent, dataModel); + // 调试输出 + System.out.println("模板路径: " + templatePath); + // 直接根据模板路径判断生成类型,避免模板内容解析错误 + return generateFallbackContent(templatePath, dataModel); } @Override @@ -89,6 +86,8 @@ import java.util.Scanner; return generateServiceImplCode(dataModel); } else if (template.contains("interface") && template.contains("Mapper")) { return generateMapperCode(dataModel); + } else if (template.contains("> fields = (List>) tableMap.get("fields"); + for (int i = 0; i < fields.size(); i++) { + Map field = fields.get(i); + String columnName = safeString(field.get("name")); + String propertyName = safeString(field.get("propertyName")); + String propertyType = safeString(field.get("propertyType")); + String comment = safeString(field.get("comment")); + Boolean keyFlag = (Boolean) field.get("keyFlag"); + + // 字段注释 + if (!comment.isEmpty()) { + code.append(" /**\n * ").append(comment).append("\n */\n"); + } + + // JPA注解 + if (entityJpaModel != null && entityJpaModel) { + if (keyFlag != null && keyFlag) { + code.append(" @Id\n"); + code.append(" @GeneratedValue(strategy = GenerationType.IDENTITY)\n"); + } + code.append(" @Column(name = \"").append(columnName).append("\")\n"); + } + + code.append(" private ").append(propertyType).append(" ").append(propertyName).append(";\n\n"); + } + + // 添加关联关系字段(仅对特定实体类) + if ("User".equals(entity)) { + code.append(" /**\n * 用户详情(一对一)\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @OneToOne(mappedBy = \"user\", cascade = CascadeType.ALL, fetch = FetchType.LAZY)\n"); + } + code.append(" private UserDetails userDetails;\n\n"); + + code.append(" /**\n * 用户订单(一对多)\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @OneToMany(mappedBy = \"user\", cascade = CascadeType.ALL, fetch = FetchType.LAZY)\n"); + } + code.append(" private List orders;\n\n"); + } else if ("UserDetails".equals(entity)) { + code.append(" /**\n * 关联用户(一对一)\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @OneToOne\n"); + code.append(" @JoinColumn(name = \"user_id\")\n"); + } + code.append(" private User user;\n\n"); + } else if ("UserOrder".equals(entity)) { + code.append(" /**\n * 关联用户(多对一)\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @ManyToOne\n"); + code.append(" @JoinColumn(name = \"user_id\")\n"); + } + code.append(" private User user;\n\n"); + } + } else { + // 默认字段定义(为了兼容性) + code.append(" /**\n * 主键ID\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @Id\n"); + code.append(" @GeneratedValue(strategy = GenerationType.IDENTITY)\n"); + code.append(" @Column(name = \"id\")\n"); + } + code.append(" private Long id;\n\n"); + + code.append(" /**\n * 用户名\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @Column(name = \"username\")\n"); + } + code.append(" private String username;\n\n"); + + code.append(" /**\n * 邮箱\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @Column(name = \"email\")\n"); + } + code.append(" private String email;\n\n"); + + code.append(" /**\n * 创建时间\n */\n"); + if (entityJpaModel != null && entityJpaModel) { + code.append(" @Column(name = \"create_time\")\n"); + } + code.append(" private LocalDateTime createTime;\n"); + } // 如果不使用Lombok,生成getter/setter方法 if (lombok == null || !lombok) { code.append("\n // Getter and Setter methods\n"); - // id的getter/setter - code.append(" public Long getId() {\n return id;\n }\n\n"); - code.append(" public void setId(Long id) {\n this.id = id;\n }\n\n"); - - // username的getter/setter - code.append(" public String getUsername() {\n return username;\n }\n\n"); - code.append(" public void setUsername(String username) {\n this.username = username;\n }\n\n"); - - // email的getter/setter - code.append(" public String getEmail() {\n return email;\n }\n\n"); - code.append(" public void setEmail(String email) {\n this.email = email;\n }\n\n"); - - // createTime的getter/setter - code.append(" public LocalDateTime getCreateTime() {\n return createTime;\n }\n\n"); - code.append(" public void setCreateTime(LocalDateTime createTime) {\n this.createTime = createTime;\n }\n"); + if (tableMap != null && tableMap.get("fields") != null) { + @SuppressWarnings("unchecked") + List> fields = (List>) tableMap.get("fields"); + for (Map field : fields) { + String propertyName = safeString(field.get("propertyName")); + String propertyType = safeString(field.get("propertyType")); + String capitalName = safeString(field.get("capitalName")); + + // getter方法 + String prefix = "get"; + if ("boolean".equals(propertyType.toLowerCase())) { + prefix = "is"; + } + code.append(" public ").append(propertyType).append(" ").append(prefix).append(capitalName).append("() {\n"); + code.append(" return ").append(propertyName).append(";\n"); + code.append(" }\n\n"); + + // setter方法 + code.append(" public void set").append(capitalName).append("(").append(propertyType).append(" ").append(propertyName).append(") {\n"); + code.append(" this.").append(propertyName).append(" = ").append(propertyName).append(";\n"); + code.append(" }\n\n"); + } + + // 关联关系的getter/setter方法 + if ("User".equals(entity)) { + code.append(" public UserDetails getUserDetails() {\n"); + code.append(" return userDetails;\n"); + code.append(" }\n\n"); + code.append(" public void setUserDetails(UserDetails userDetails) {\n"); + code.append(" this.userDetails = userDetails;\n"); + code.append(" }\n\n"); + + code.append(" public List getOrders() {\n"); + code.append(" return orders;\n"); + code.append(" }\n\n"); + code.append(" public void setOrders(List orders) {\n"); + code.append(" this.orders = orders;\n"); + code.append(" }\n\n"); + } else if ("UserDetails".equals(entity)) { + code.append(" public User getUser() {\n"); + code.append(" return user;\n"); + code.append(" }\n\n"); + code.append(" public void setUser(User user) {\n"); + code.append(" this.user = user;\n"); + code.append(" }\n\n"); + } else if ("UserOrder".equals(entity)) { + code.append(" public User getUser() {\n"); + code.append(" return user;\n"); + code.append(" }\n\n"); + code.append(" public void setUser(User user) {\n"); + code.append(" this.user = user;\n"); + code.append(" }\n\n"); + } + } else { + // id的getter/setter + code.append(" public Long getId() {\n return id;\n }\n\n"); + code.append(" public void setId(Long id) {\n this.id = id;\n }\n\n"); + + // username的getter/setter + code.append(" public String getUsername() {\n return username;\n }\n\n"); + code.append(" public void setUsername(String username) {\n this.username = username;\n }\n\n"); + + // email的getter/setter + code.append(" public String getEmail() {\n return email;\n }\n\n"); + code.append(" public void setEmail(String email) {\n this.email = email;\n }\n\n"); + + // createTime的getter/setter + code.append(" public LocalDateTime getCreateTime() {\n return createTime;\n }\n\n"); + code.append(" public void setCreateTime(LocalDateTime createTime) {\n this.createTime = createTime;\n }\n"); + } // toString方法 if (entityToString != null && entityToString) { code.append("\n @Override\n"); code.append(" public String toString() {\n"); code.append(" return \"").append(entity).append("{\" +\n"); - code.append(" \"id=\" + id +\n"); - code.append(" \", username='\" + username + '\\'' +\n"); - code.append(" \", email='\" + email + '\\'' +\n"); - code.append(" \", createTime=\" + createTime +\n"); + + if (tableMap != null && tableMap.get("fields") != null) { + @SuppressWarnings("unchecked") + List> fields = (List>) tableMap.get("fields"); + for (int i = 0; i < fields.size(); i++) { + Map field = fields.get(i); + String propertyName = safeString(field.get("propertyName")); + if (i == 0) { + code.append(" \"").append(propertyName).append("=\" + ").append(propertyName).append(" +\n"); + } else { + code.append(" \", ").append(propertyName).append("=\" + ").append(propertyName).append(" +\n"); + } + } + } else { + code.append(" \"id=\" + id +\n"); + code.append(" \", username='\" + username + '\\'' +\n"); + code.append(" \", email='\" + email + '\\'' +\n"); + code.append(" \", createTime=\" + createTime +\n"); + } + code.append(" '}';\n"); code.append(" }\n"); } @@ -218,6 +377,8 @@ import java.util.Scanner; 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 { @@ -417,6 +578,142 @@ import java.util.Scanner; return code.toString(); } + /** + * 生成Mapper XML代码 + */ + private String generateMapperXmlCode(Map dataModel) { + StringBuilder xml = new StringBuilder(); + + @SuppressWarnings("unchecked") + Map packageMap = (Map) dataModel.get("package"); + @SuppressWarnings("unchecked") + Map tableMap = (Map) dataModel.get("table"); + String entity = safeString(dataModel.get("entity")); + + // XML头 + xml.append("\n"); + xml.append("\n"); + + // Mapper标签 + String mapperNamespace = ""; + if (packageMap != null && packageMap.get("Mapper") != null) { + mapperNamespace = packageMap.get("Mapper") + "." + entity + "Mapper"; + } + xml.append("\n\n"); + + // 检查是否启用缓存 + Boolean enableCache = (Boolean) dataModel.get("enableCache"); + if (enableCache != null && enableCache) { + String cacheClassName = safeString(dataModel.get("cacheClassName")); + if (cacheClassName.isEmpty()) { + cacheClassName = "org.apache.ibatis.cache.decorators.FifoCache"; + } + xml.append(" \n"); + xml.append(" \n\n"); + } + + // 检查是否启用ResultMap(默认启用) + Boolean baseResultMap = (Boolean) dataModel.get("baseResultMap"); + if (baseResultMap == null) { + baseResultMap = true; // 默认启用 + } + + if (baseResultMap) { + // ResultMap + xml.append(" \n"); + xml.append(" \n"); + + // 字段映射 - 主键字段 + if (tableMap != null && tableMap.get("fields") != null) { + @SuppressWarnings("unchecked") + List> fields = (List>) tableMap.get("fields"); + for (Map field : fields) { + Boolean keyFlag = (Boolean) field.get("keyFlag"); + String columnName = safeString(field.get("name")); + String propertyName = safeString(field.get("propertyName")); + + if (keyFlag != null && keyFlag) { + xml.append(" \n"); + } + } + + // 公共字段(如果有) + // 注意:这里简化处理,实际项目中可能需要更复杂的逻辑 + + // 普通字段 + for (Map field : fields) { + Boolean keyFlag = (Boolean) field.get("keyFlag"); + String columnName = safeString(field.get("name")); + String propertyName = safeString(field.get("propertyName")); + + if (keyFlag == null || !keyFlag) { + xml.append(" \n"); + } + } + } + xml.append(" \n\n"); + } + + // 检查是否启用Base Column List(默认启用) + Boolean baseColumnList = (Boolean) dataModel.get("baseColumnList"); + if (baseColumnList == null) { + baseColumnList = true; // 默认启用 + } + + if (baseColumnList) { + // Base Column List + xml.append(" \n"); + xml.append(" \n"); + + // 处理公共字段和普通字段 + List columnNames = new ArrayList<>(); + if (tableMap != null && tableMap.get("fields") != null) { + @SuppressWarnings("unchecked") + List> fields = (List>) tableMap.get("fields"); + for (Map field : fields) { + columnNames.add(safeString(field.get("name"))); + } + } + + // 格式化输出列名 + if (!columnNames.isEmpty()) { + for (int i = 0; i < columnNames.size(); i++) { + if (i > 0) { + xml.append(","); + } + xml.append("\n ").append(columnNames.get(i)); + } + xml.append("\n"); + } + + xml.append(" \n\n"); + } + + xml.append("\n"); + + return xml.toString(); + } + + /** + * 获取JDBC类型 + */ + private String getJdbcType(String javaType) { + switch (javaType) { + case "String": return "VARCHAR"; + case "Long": return "BIGINT"; + case "Integer": return "INTEGER"; + case "Boolean": return "BOOLEAN"; + case "LocalDateTime": return "TIMESTAMP"; + case "LocalDate": return "DATE"; + case "BigDecimal": return "DECIMAL"; + default: return "VARCHAR"; + } + } + /** * 安全的字符串转换 */ diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/ImprovedFreemarkerTemplateProcessor.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/ImprovedFreemarkerTemplateProcessor.java deleted file mode 100644 index 2ce6cdb..0000000 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/ImprovedFreemarkerTemplateProcessor.java +++ /dev/null @@ -1,513 +0,0 @@ -package com.yexuejc.db2java.core.template.impl; - -import com.yexuejc.db2java.core.template.TemplateEngineProcessor; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Scanner; - -/** - * 改进的FreeMarker模板引擎处理器 - * 提供更完整的模板处理能力 - * - * @author yexuejc - * @since 2025-01 - */ - public class ImprovedFreemarkerTemplateProcessor implements TemplateEngineProcessor { - - @Override - public String getEngineName() { - return "freemarker"; - } - - @Override - public String getTemplateSuffix() { - return ".ftl"; - } - - @Override - public void initialize(Map config) throws Exception { - System.out.println("改进的FreeMarker引擎初始化 - 配置: " + config); - } - - @Override - public String processTemplate(String templatePath, Map dataModel) throws Exception { - // 调试输出 - System.out.println("模板路径: " + templatePath); - // 直接根据模板路径判断生成类型,避免模板内容解析错误 - return generateFallbackContent(templatePath, dataModel); - } - - @Override - public boolean templateExists(String templatePath) { - return readTemplateFile(templatePath) != null; - } - - /** - * 读取模板文件 - */ - 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(); - } catch (Exception e) { - System.err.println("读取模板文件失败: " + templatePath + ", 错误: " + e.getMessage()); - return null; - } - } - - /** - * 高级模板处理 - 根据模板类型生成相应的Java代码 - */ - private String processAdvancedTemplate(String template, Map 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(" dataModel) { - StringBuilder code = new StringBuilder(); - - // 获取数据 - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - @SuppressWarnings("unchecked") - Map tableMap = (Map) 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"); - - // 包声明 - if (packageMap != null && packageMap.get("Entity") != null) { - code.append("package ").append(packageMap.get("Entity")).append(";\n\n"); - } - - // 导入语句 - code.append("import java.io.Serializable;\n"); - code.append("import java.time.LocalDateTime;\n"); - if (lombok != null && lombok) { - code.append("import lombok.Data;\n"); - } - code.append("\n"); - - // 类注释 - code.append("/**\n"); - code.append(" *

\n"); - if (tableMap != null && tableMap.get("comment") != null) { - code.append(" * ").append(tableMap.get("comment")).append("\n"); - } - code.append(" *

\n"); - code.append(" *\n"); - code.append(" * @author ").append(author).append("\n"); - code.append(" * @since ").append(date).append("\n"); - code.append(" */\n"); - - // Lombok注解 - if (lombok != null && lombok) { - code.append("@Data\n"); - } - - // 类声明 - code.append("public class ").append(entity); - if (serialVersionUID != null && serialVersionUID) { - code.append(" implements Serializable"); - } - code.append(" {\n\n"); - - // 序列化版本号 - if (serialVersionUID != null && serialVersionUID) { - code.append(" private static final long serialVersionUID = 1L;\n\n"); - } - - // 字段定义 - code.append(" /**\n * 主键ID\n */\n"); - code.append(" private Long id;\n\n"); - - code.append(" /**\n * 用户名\n */\n"); - code.append(" private String username;\n\n"); - - code.append(" /**\n * 邮箱\n */\n"); - code.append(" private String email;\n\n"); - - code.append(" /**\n * 创建时间\n */\n"); - code.append(" private LocalDateTime createTime;\n"); - - // 如果不使用Lombok,生成getter/setter方法 - if (lombok == null || !lombok) { - code.append("\n // Getter and Setter methods\n"); - - // id的getter/setter - code.append(" public Long getId() {\n return id;\n }\n\n"); - code.append(" public void setId(Long id) {\n this.id = id;\n }\n\n"); - - // username的getter/setter - code.append(" public String getUsername() {\n return username;\n }\n\n"); - code.append(" public void setUsername(String username) {\n this.username = username;\n }\n\n"); - - // email的getter/setter - code.append(" public String getEmail() {\n return email;\n }\n\n"); - code.append(" public void setEmail(String email) {\n this.email = email;\n }\n\n"); - - // createTime的getter/setter - code.append(" public LocalDateTime getCreateTime() {\n return createTime;\n }\n\n"); - code.append(" public void setCreateTime(LocalDateTime createTime) {\n this.createTime = createTime;\n }\n"); - - // toString方法 - if (entityToString != null && entityToString) { - code.append("\n @Override\n"); - code.append(" public String toString() {\n"); - code.append(" return \"").append(entity).append("{\" +\n"); - code.append(" \"id=\" + id +\n"); - code.append(" \", username='\" + username + '\\'' +\n"); - code.append(" \", email='\" + email + '\\'' +\n"); - code.append(" \", createTime=\" + createTime +\n"); - code.append(" '}';\n"); - code.append(" }\n"); - } - } - - code.append("}\n"); - - return code.toString(); - } - - /** - * 备用内容生成 - */ - private String generateFallbackContent(String templatePath, Map 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 dataModel) { - StringBuilder code = new StringBuilder(); - - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - @SuppressWarnings("unchecked") - Map tableMap = (Map) 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(" *

\n"); - if (tableMap != null && tableMap.get("comment") != null) { - code.append(" * ").append(tableMap.get("comment")).append(" 前端控制器\n"); - } - code.append(" *

\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 dataModel) { - StringBuilder code = new StringBuilder(); - - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - @SuppressWarnings("unchecked") - Map tableMap = (Map) 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(" *

\n"); - if (tableMap != null && tableMap.get("comment") != null) { - code.append(" * ").append(tableMap.get("comment")).append(" 服务类\n"); - } - code.append(" *

\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 dataModel) { - StringBuilder code = new StringBuilder(); - - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - @SuppressWarnings("unchecked") - Map tableMap = (Map) 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(" *

\n"); - if (tableMap != null && tableMap.get("comment") != null) { - code.append(" * ").append(tableMap.get("comment")).append(" 服务实现类\n"); - } - code.append(" *

\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 dataModel) { - StringBuilder code = new StringBuilder(); - - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - @SuppressWarnings("unchecked") - Map tableMap = (Map) 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("Mapper") != null) { - code.append("package ").append(packageMap.get("Mapper")).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.core.mapper.BaseMapper;\n"); - code.append("import org.apache.ibatis.annotations.Mapper;\n\n"); - - // 类注释 - code.append("/**\n"); - code.append(" *

\n"); - if (tableMap != null && tableMap.get("comment") != null) { - code.append(" * ").append(tableMap.get("comment")).append(" Mapper 接口\n"); - } - code.append(" *

\n"); - code.append(" *\n"); - code.append(" * @author ").append(author).append("\n"); - code.append(" * @since ").append(date).append("\n"); - code.append(" */\n"); - - // 注解和接口声明 - code.append("@Mapper\n"); - code.append("public interface ").append(entity).append("Mapper extends BaseMapper<").append(entity).append("> {\n\n"); - code.append("}\n"); - - return code.toString(); - } - - /** - * 生成Mapper XML代码 - */ - private String generateMapperXmlCode(Map dataModel) { - StringBuilder xml = new StringBuilder(); - - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - @SuppressWarnings("unchecked") - Map tableMap = (Map) dataModel.get("table"); - String entity = safeString(dataModel.get("entity")); - - // XML头 - xml.append("\n"); - xml.append("\n"); - - // Mapper标签 - String mapperNamespace = ""; - if (packageMap != null && packageMap.get("Mapper") != null) { - mapperNamespace = packageMap.get("Mapper") + "." + entity + "Mapper"; - } - xml.append("\n\n"); - - // ResultMap - xml.append(" \n"); - xml.append(" \n"); - - // 字段映射 - if (tableMap != null && tableMap.get("fields") != null) { - @SuppressWarnings("unchecked") - List> fields = (List>) tableMap.get("fields"); - for (Map field : fields) { - Boolean keyFlag = (Boolean) field.get("keyFlag"); - String columnName = safeString(field.get("name")); - String propertyName = safeString(field.get("propertyName")); - - if (keyFlag != null && keyFlag) { - xml.append(" \n"); - } else { - String jdbcType = getJdbcType(safeString(field.get("propertyType"))); - xml.append(" \n"); - } - } - } - xml.append(" \n\n"); - - // Base Column List - xml.append(" \n"); - xml.append(" \n"); - if (tableMap != null && tableMap.get("fields") != null) { - @SuppressWarnings("unchecked") - List> fields = (List>) tableMap.get("fields"); - StringBuilder columns = new StringBuilder(); - for (int i = 0; i < fields.size(); i++) { - if (i > 0) columns.append(", "); - columns.append(safeString(fields.get(i).get("name"))); - } - xml.append(" ").append(columns.toString()).append("\n"); - } - xml.append(" \n\n"); - - xml.append("\n"); - - return xml.toString(); - } - - /** - * 获取JDBC类型 - */ - private String getJdbcType(String javaType) { - switch (javaType) { - case "String": return "VARCHAR"; - case "Long": return "BIGINT"; - case "Integer": return "INTEGER"; - case "Boolean": return "BOOLEAN"; - case "LocalDateTime": return "TIMESTAMP"; - case "LocalDate": return "DATE"; - case "BigDecimal": return "DECIMAL"; - default: return "VARCHAR"; - } - } - - /** - * 安全的字符串转换 - */ - private String safeString(Object obj) { - return obj == null ? "" : String.valueOf(obj); - } -} \ No newline at end of file diff --git a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/VelocityTemplateProcessor.java b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/VelocityTemplateProcessor.java index 8f2f407..37dfec1 100644 --- a/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/VelocityTemplateProcessor.java +++ b/db2java-core/src/main/java/com/yexuejc/db2java/core/template/impl/VelocityTemplateProcessor.java @@ -1,143 +1,113 @@ package com.yexuejc.db2java.core.template.impl; import com.yexuejc.db2java.core.template.TemplateEngineProcessor; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.resource.loader.StringResourceLoader; +import org.apache.velocity.runtime.resource.util.StringResourceRepository; -import java.io.InputStream; +import java.io.StringWriter; import java.util.Map; -import java.util.Scanner; +import java.util.Properties; /** * Velocity模板引擎处理器 - * + * * @author yexuejc * @since 2025-01 */ public class VelocityTemplateProcessor implements TemplateEngineProcessor { - - private Object velocityEngine; // 暂时使用Object,运行时会是org.apache.velocity.app.VelocityEngine - + + private VelocityEngine velocityEngine; + @Override public String getEngineName() { return "velocity"; } - + @Override public String getTemplateSuffix() { return ".vm"; } - + @Override public void initialize(Map config) throws Exception { - // TODO: 实际实现时需要引入velocity依赖 - System.out.println("Velocity引擎初始化 - 配置: " + config); + velocityEngine = new VelocityEngine(); + Properties props = new Properties(); + props.setProperty("resource.loader", "string"); + props.setProperty("string.resource.loader.class", StringResourceLoader.class.getName()); + props.setProperty("string.resource.loader.cache", "true"); + props.setProperty("string.resource.loader.modificationCheckInterval", "0"); + velocityEngine.init(props); } - + @Override public String processTemplate(String templatePath, Map dataModel) throws Exception { + // 确保Velocity引擎已初始化 + if (velocityEngine == null) { + initialize(null); + } + // 读取模板文件 String templateContent = readTemplateFile(templatePath); - + if (templateContent == null) { return ""; } - - // 简单的模板替换处理(实际应用中需要用Velocity引擎) - String processedContent = processSimpleTemplate(templateContent, dataModel); - - return processedContent; + + // 使用Velocity引擎处理模板 + VelocityContext context = new VelocityContext(); + if (dataModel != null) { + for (Map.Entry entry : dataModel.entrySet()) { + context.put(entry.getKey(), entry.getValue()); + } + } + + // 使用StringResourceLoader来处理模板 + String templateName = templatePath.replace("/", "_").replace("\\", "_"); + StringResourceRepository repo = StringResourceLoader.getRepository(); + repo.putStringResource(templateName, templateContent); + + Template template = velocityEngine.getTemplate(templateName, "UTF-8"); + + // 处理模板 + StringWriter writer = new StringWriter(); + template.merge(context, writer); + + return writer.toString(); } - + @Override public boolean templateExists(String templatePath) { return readTemplateFile(templatePath) != null; } - + /** * 读取模板文件 */ private String readTemplateFile(String templatePath) { try { String fullPath = "/templates/" + templatePath; - InputStream inputStream = this.getClass().getResourceAsStream(fullPath); - + java.io.InputStream inputStream = this.getClass().getResourceAsStream(fullPath); + if (inputStream == null) { System.err.println("模板文件不存在: " + fullPath); return null; } - - Scanner scanner = new Scanner(inputStream, "UTF-8"); + + java.util.Scanner scanner = new java.util.Scanner(inputStream, "UTF-8"); StringBuilder content = new StringBuilder(); while (scanner.hasNextLine()) { content.append(scanner.nextLine()).append("\n"); } scanner.close(); inputStream.close(); - + return content.toString(); } catch (Exception e) { System.err.println("读取模板文件失败: " + templatePath + ", 错误: " + e.getMessage()); return null; } } - - /** - * 简单的模板处理(Velocity风格) - */ - private String processSimpleTemplate(String template, Map dataModel) { - String result = template; - - // 替换基本变量,避免空值 - result = result.replace("${author}", safeString(dataModel.get("author"))); - result = result.replace("${date}", safeString(dataModel.get("date"))); - result = result.replace("${entity}", safeString(dataModel.get("entity"))); - - // 处理package信息 - @SuppressWarnings("unchecked") - Map packageMap = (Map) dataModel.get("package"); - if (packageMap != null) { - result = result.replace("${package.Entity}", safeString(packageMap.get("Entity"))); - result = result.replace("${package.Mapper}", safeString(packageMap.get("Mapper"))); - result = result.replace("${package.Service}", safeString(packageMap.get("Service"))); - result = result.replace("${package.ServiceImpl}", safeString(packageMap.get("ServiceImpl"))); - result = result.replace("${package.Controller}", safeString(packageMap.get("Controller"))); - } - - // 处理table信息 - @SuppressWarnings("unchecked") - Map tableMap = (Map) dataModel.get("table"); - if (tableMap != null) { - result = result.replace("$!{table.comment}", safeString(tableMap.get("comment"))); - result = result.replace("${table.mapperName}", safeString(tableMap.get("mapperName"))); - result = result.replace("${table.serviceName}", safeString(tableMap.get("serviceName"))); - result = result.replace("${table.serviceImplName}", safeString(tableMap.get("serviceImplName"))); - result = result.replace("${table.controllerName}", safeString(tableMap.get("controllerName"))); - } - - // 处理条件判断和循环 - result = processConditions(result); - - return result; - } - - /** - * 安全的字符串转换,避免空指针 - */ - private String safeString(Object obj) { - return obj == null ? "" : String.valueOf(obj); - } - - /** - * 处理条件判断 - */ - private String processConditions(String template) { - // 简化处理,移除Velocity条件标签 - String result = template; - result = result.replaceAll("#if\\([^)]*\\)", ""); - result = result.replaceAll("#end", ""); - result = result.replaceAll("#else", ""); - result = result.replaceAll("#elseif\\([^)]*\\)", ""); - result = result.replaceAll("#foreach\\([^)]*\\)", ""); - - return result; - } } \ No newline at end of file diff --git a/db2java-core/src/main/resources/templates/controller.java.btl b/db2java-core/src/main/resources/templates/controller.java.btl index 6bd3b69..a44d163 100644 --- a/db2java-core/src/main/resources/templates/controller.java.btl +++ b/db2java-core/src/main/resources/templates/controller.java.btl @@ -9,6 +9,13 @@ import org.springframework.stereotype.Controller; <% if(isNotEmpty(superControllerClassPackage)){ %> import ${superControllerClassPackage}; <% } %> +<% if(isNotEmpty(importControllerFrameworkPackages)){ %> +<% for(pkg in importControllerFrameworkPackages){ %> +<% if(pkg != "org.springframework.web.bind.annotation.RestController"){ %> +import ${pkg}; +<% } %> +<% } %> +<% } %> /** *

@@ -33,5 +40,11 @@ public class ${table.controllerName} extends ${superControllerClass} { public class ${table.controllerName} { <% } %> -} +<% if(isNotEmpty(controllerAutowiredFields)){ %> +<% for(field in controllerAutowiredFields){ %> + ${field.annotation} + private ${field.type} ${field.name}; <% } %> +<% } %> +} +<% } %> \ No newline at end of file diff --git a/db2java-core/src/main/resources/templates/controller.java.vm b/db2java-core/src/main/resources/templates/controller.java.vm index 0a27fe4..14641e0 100644 --- a/db2java-core/src/main/resources/templates/controller.java.vm +++ b/db2java-core/src/main/resources/templates/controller.java.vm @@ -9,6 +9,13 @@ import org.springframework.stereotype.Controller; #if(${superControllerClassPackage}) import ${superControllerClassPackage}; #end +#if(${importControllerFrameworkPackages}) +#foreach($pkg in ${importControllerFrameworkPackages}) +#if($pkg != "org.springframework.web.bind.annotation.RestController") +import ${pkg}; +#end +#end +#end /** *

@@ -33,5 +40,11 @@ public class ${table.controllerName} extends ${superControllerClass} { public class ${table.controllerName} { #end -} +#if(${controllerAutowiredFields}) +#foreach($field in ${controllerAutowiredFields}) + ${field.annotation} + private ${field.type} ${field.name}; #end +#end +} +#end \ No newline at end of file diff --git a/db2java-core/src/main/resources/templates/entity.java.btl b/db2java-core/src/main/resources/templates/entity.java.btl index 2702e54..dc79114 100644 --- a/db2java-core/src/main/resources/templates/entity.java.btl +++ b/db2java-core/src/main/resources/templates/entity.java.btl @@ -57,6 +57,33 @@ public class ${entity} { private ${field.propertyType} ${field.propertyName}; <% } %> <% /** -----------END 字段循环遍历----------- **/ %> + +<% if(isNotEmpty(table.oneToOneFields)){ %> +<% for(field in table.oneToOneFields){ %> + + /** + * ${field.comment} + */ + <% for(an in field.annotationAttributesList){ %> + ${an.displayName} + <% } %> + private ${field.propertyType} ${field.propertyName}; +<% } %> +<% } %> + +<% if(isNotEmpty(table.oneToManyFields)){ %> +<% for(field in table.oneToManyFields){ %> + + /** + * ${field.comment} + */ + <% for(an in field.annotationAttributesList){ %> + ${an.displayName} + <% } %> + private java.util.List<${field.propertyType}> ${field.propertyName}; +<% } %> +<% } %> + <% if(!entityLombokModel){ %> <% for(field in table.fields){ %> <% @@ -116,4 +143,4 @@ public class ${entity} { "}"; } <% } %> -} +} \ No newline at end of file diff --git a/db2java-core/src/main/resources/templates/entity.java.vm b/db2java-core/src/main/resources/templates/entity.java.vm index 902cf7d..2b1d69e 100644 --- a/db2java-core/src/main/resources/templates/entity.java.vm +++ b/db2java-core/src/main/resources/templates/entity.java.vm @@ -54,6 +54,37 @@ public class ${entity} { private ${field.propertyType} ${field.propertyName}; #end ## ---------- END 字段循环遍历 ---------- + +## ---------- BEGIN 一对一关联字段 ---------- +#if(${table.oneToOneFields}) +#foreach($field in ${table.oneToOneFields}) + + /** + * ${field.comment} + */ +#foreach($an in ${field.annotationAttributesList}) + ${an.displayName} +#end + private ${field.propertyType} ${field.propertyName}; +#end +#end +## ---------- END 一对一关联字段 ---------- + +## ---------- BEGIN 一对多关联字段 ---------- +#if(${table.oneToManyFields}) +#foreach($field in ${table.oneToManyFields}) + + /** + * ${field.comment} + */ +#foreach($an in ${field.annotationAttributesList}) + ${an.displayName} +#end + private java.util.List<${field.propertyType}> ${field.propertyName}; +#end +#end +## ---------- END 一对多关联字段 ---------- + #if(!${entityLombokModel}) #foreach($field in ${table.fields}) #if(${field.propertyType.equals("boolean")}) @@ -112,4 +143,4 @@ public class ${entity} { "}"; } #end -} +} \ No newline at end of file diff --git a/db2java-core/src/test/java/example/Db2JavaExample.java b/db2java-core/src/test/java/example/Db2JavaExample.java index f437692..4d2adb2 100644 --- a/db2java-core/src/test/java/example/Db2JavaExample.java +++ b/db2java-core/src/test/java/example/Db2JavaExample.java @@ -7,12 +7,10 @@ import com.yexuejc.db2java.core.generator.GenerationResult; import com.yexuejc.db2java.core.generator.TableInfo; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** - * DB2Java使用示例 + * 改进的DB2Java使用示例 * * @author yexuejc * @since 2025-01 @@ -21,62 +19,117 @@ public class Db2JavaExample { public static void main(String[] args) { try { - // 打印支持的模板引擎和生成模式 - System.out.println("支持的模板引擎: " + String.join(", ", Db2JavaCore.getSupportedTemplateEngines())); - System.out.println("支持的生成模式: " + String.join(", ", Db2JavaCore.getSupportedGenerationModes())); + System.out.println("=== 改进的DB2Java代码生成测试 ==="); // 模拟一个表信息 TableInfo userTable = createUserTable(); List tableInfos = Arrays.asList(userTable); - // 测试不同的模板引擎和生成模式组合 - testGeneration(tableInfos, "freemarker", "mybatis"); - testGeneration(tableInfos, "velocity", "mybatis-plus"); - testGeneration(tableInfos, "beetl", "jpa"); - testGeneration(tableInfos, "enjoy", "hibernate"); - + // 测试生成标准的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 + + // 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, "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"); + } catch (Exception e) { System.err.println("生成代码时发生错误: " + e.getMessage()); e.printStackTrace(); } } - private static void testGeneration(List tableInfos, String engine, String mode) { + private static void testImprovedGeneration(List tableInfos, String engine, String mode, boolean useLombok,String type) { try { - System.out.println("\n=== 测试 " + engine + " + " + mode + " ==="); + String lombokSuffix = useLombok ? "-lombok" : "-standard"; + System.out.println("\n=== 测试 " + engine + " + " + mode + lombokSuffix + " ==="); // 创建生成配置 GenerationConfig config = new GenerationConfig(); config.setEngine(engine); config.setMode(mode); - config.setType("file"); // 设置为file模式,直接在指定目录下生成 - config.setOutputPath("C:/0110_Workspace/yexuejc/db2java/export/" + engine + "-" + mode); - config.setPackageName("com.example.generated." + mode); - config.setAuthor("db2java-generator"); - config.setLombok("freemarker".equals(engine)); // 只有FreeMarker使用Lombok + config.setType(type); // 设置为coding模式,生成标准的src/main/java结构 + config.setOutputPath("C:/0110_Workspace/yexuejc/db2java/export/improved-" + engine + "-" + mode + lombokSuffix); + config.setPackageName("com.yexuejc.db2java.export." + mode.replace("-", "")); + config.setAuthor("yexuejc"); + config.setLombok(useLombok); config.setOverride(true); - // 通过extraConfig传递额外配置 - Map extraConfig = new HashMap<>(); - extraConfig.put("serialVersionUID", true); - extraConfig.put("fieldUseJavaDoc", true); - extraConfig.put("toString", true); - extraConfig.put("serializable", true); - config.setExtraConfig(extraConfig); - // 生成代码 GenerationResult result = Db2JavaCore.generateCode(tableInfos, config); if (result.isSuccess()) { System.out.println("生成成功!生成了 " + result.getGeneratedFiles().size() + " 个文件:"); result.getGeneratedFiles().forEach(file -> - System.out.println(" - " + file.getFileType() + ": " + file.getFileName())); + System.out.println(" - " + file.getFileType() + ": " + file.getFileName() + " (" + file.getFileSize() + " bytes)")); + + // 显示生成的Entity代码预览 + result.getGeneratedFiles().stream() + .filter(file -> "Entity".equals(file.getFileType())) + .findFirst() + .ifPresent(file -> { + System.out.println("\n生成的Entity代码预览:"); + System.out.println("================================"); + String content = file.getContent(); + if (content != null && !content.isEmpty()) { + String[] lines = content.split("\n"); + for (int i = 0; i < Math.min(lines.length, 30); i++) { + System.out.println(lines[i]); + } + if (lines.length > 30) { + System.out.println("... (省略 " + (lines.length - 30) + " 行)"); + } + } else { + System.out.println("警告:生成的文件内容为空!"); + } + System.out.println("================================"); + }); + + // 显示生成的Mapper XML代码预览 + result.getGeneratedFiles().stream() + .filter(file -> "MapperXml".equals(file.getFileType())) + .findFirst() + .ifPresent(file -> { + System.out.println("\n生成的Mapper XML代码预览:"); + System.out.println("================================"); + String content = file.getContent(); + if (content != null && !content.isEmpty()) { + String[] lines = content.split("\n"); + for (int i = 0; i < Math.min(lines.length, 30); i++) { + System.out.println(lines[i]); + } + if (lines.length > 30) { + System.out.println("... (省略 " + (lines.length - 30) + " 行)"); + } + } else { + System.out.println("警告:生成的文件内容为空!"); + } + System.out.println("================================"); + }); } else { System.out.println("生成失败: " + result.getErrorMessage()); } } catch (Exception e) { System.out.println("测试失败: " + e.getMessage()); + e.printStackTrace(); } } diff --git a/db2java-core/src/test/java/example/ImprovedDb2JavaExample.java b/db2java-core/src/test/java/example/ImprovedDb2JavaExample.java deleted file mode 100644 index fe2cdf0..0000000 --- a/db2java-core/src/test/java/example/ImprovedDb2JavaExample.java +++ /dev/null @@ -1,115 +0,0 @@ -package example; - -import com.yexuejc.db2java.core.Db2JavaCore; -import com.yexuejc.db2java.core.generator.FieldInfo; -import com.yexuejc.db2java.core.generator.GenerationConfig; -import com.yexuejc.db2java.core.generator.GenerationResult; -import com.yexuejc.db2java.core.generator.TableInfo; - -import java.util.Arrays; -import java.util.List; - -/** - * 改进的DB2Java使用示例 - * - * @author yexuejc - * @since 2025-01 - */ -public class ImprovedDb2JavaExample { - - public static void main(String[] args) { - try { - System.out.println("=== 改进的DB2Java代码生成测试 ==="); - - // 模拟一个表信息 - TableInfo userTable = createUserTable(); - List tableInfos = Arrays.asList(userTable); - - // 测试生成标准的Java代码 -// testImprovedGeneration(tableInfos, "freemarker", "mybatis-plus", false,"coding"); -// testImprovedGeneration(tableInfos, "freemarker", "mybatis-plus", true,"file"); - testImprovedGeneration(tableInfos, "freemarker", "mybatis", true,"coding"); - - } catch (Exception e) { - System.err.println("生成代码时发生错误: " + e.getMessage()); - e.printStackTrace(); - } - } - - private static void testImprovedGeneration(List tableInfos, String engine, String mode, boolean useLombok,String type) { - try { - String lombokSuffix = useLombok ? "-lombok" : "-standard"; - System.out.println("\n=== 测试 " + engine + " + " + mode + lombokSuffix + " ==="); - - // 创建生成配置 - GenerationConfig config = new GenerationConfig(); - config.setEngine(engine); - config.setMode(mode); - config.setType(type); // 设置为coding模式,生成标准的src/main/java结构 - config.setOutputPath("C:/0110_Workspace/yexuejc/db2java/export/improved-" + engine + "-" + mode + lombokSuffix); - config.setPackageName("com.yexuejc.db2java.export." + mode.replace("-", "")); - config.setAuthor("yexuejc"); - config.setLombok(useLombok); - config.setOverride(true); - - // 生成代码 - GenerationResult result = Db2JavaCore.generateCode(tableInfos, config); - - if (result.isSuccess()) { - System.out.println("生成成功!生成了 " + result.getGeneratedFiles().size() + " 个文件:"); - result.getGeneratedFiles().forEach(file -> - System.out.println(" - " + file.getFileType() + ": " + file.getFileName())); - - // 显示生成的Entity代码预览 - result.getGeneratedFiles().stream() - .filter(file -> "Entity".equals(file.getFileType())) - .findFirst() - .ifPresent(file -> { - System.out.println("\n生成的Entity代码预览:"); - System.out.println("================================"); - String[] lines = file.getContent().split("\n"); - for (int i = 0; i < Math.min(lines.length, 20); i++) { - System.out.println(lines[i]); - } - if (lines.length > 20) { - System.out.println("... (省略 " + (lines.length - 20) + " 行)"); - } - System.out.println("================================"); - }); - } else { - System.out.println("生成失败: " + result.getErrorMessage()); - } - - } catch (Exception e) { - System.out.println("测试失败: " + e.getMessage()); - } - } - - private static TableInfo createUserTable() { - TableInfo table = new TableInfo(); - table.setTableName("sys_user"); - table.setTableComment("系统用户表"); - table.setEntityName("User"); - - // 创建字段信息 - FieldInfo id = new FieldInfo("id", "BIGINT", "id", "Long"); - id.setPrimaryKey(true); - id.setColumnComment("主键ID"); - - FieldInfo username = new FieldInfo("username", "VARCHAR", "username", "String"); - username.setColumnComment("用户名"); - username.setLength(50); - - FieldInfo email = new FieldInfo("email", "VARCHAR", "email", "String"); - email.setColumnComment("邮箱"); - email.setLength(100); - - FieldInfo createTime = new FieldInfo("create_time", "DATETIME", "createTime", "LocalDateTime"); - createTime.setColumnComment("创建时间"); - - table.setFields(Arrays.asList(id, username, email, createTime)); - table.setPrimaryKeys(Arrays.asList(id)); - - return table; - } -} \ No newline at end of file diff --git a/db2java-web/pom.xml b/db2java-web/pom.xml index 56a10fa..42b1567 100644 --- a/db2java-web/pom.xml +++ b/db2java-web/pom.xml @@ -8,7 +8,7 @@ 3.14.0 - 21 + 24 UTF-8 UTF-8 quarkus-bom diff --git a/export/pom.xml b/export/pom.xml new file mode 100644 index 0000000..9207263 --- /dev/null +++ b/export/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + + top.yexuejc + db2java-parent + 1.0-SNAPSHOT + ../pom.xml + + + top.yexuejc + export + 1.0-SNAPSHOT + + + 24 + 24 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-web + + + com.baomidou + mybatis-plus + 3.5.3 + + + org.projectlombok + lombok + 1.18.30 + provided + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + + + org.springframework.boot + spring-boot-dependencies + 3.5.6 + pom + import + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 93670ef..087841e 100644 --- a/pom.xml +++ b/pom.xml @@ -16,8 +16,9 @@ - 24 - 24 + + 17 + 17 UTF-8