diff --git a/src/main/java/space/caoshd/otone/builder/ColumnBuilder.java b/src/main/java/space/caoshd/otone/builder/ColumnBuilder.java index 8a6f5e2..ea109b7 100644 --- a/src/main/java/space/caoshd/otone/builder/ColumnBuilder.java +++ b/src/main/java/space/caoshd/otone/builder/ColumnBuilder.java @@ -45,9 +45,9 @@ public class ColumnBuilder { ColumnInfo result = new ColumnInfo(); String columnName = SQL_HELPER.getLabelColumnName(); result.setColumnName(column.get(columnName)); - String fieldName = StrUtils.toCamelCase(result.getColumnName(), false); + String fieldName = StrUtils.snakeToCamelCase(result.getColumnName()); result.setFieldName(fieldName); - String fieldNameCap = StrUtils.toCamelCase(result.getColumnName(), true); + String fieldNameCap = StrUtils.snakeToPascalCase(result.getColumnName()); result.setFieldNameCap(fieldNameCap); String columnComment = SQL_HELPER.getLabelColumnComment(); @@ -57,6 +57,9 @@ public class ColumnBuilder { result.setDbType(column.get(dbType)); String javaType = TypeUtils.toJavaType(result.getDbType()); result.setJavaType(javaType); + + result.setDecimalType(TypeUtils.isDecimalType(javaType)); + result.setDateType(TypeUtils.isDateType(javaType)); String autoIncrement = SQL_HELPER.getLabelAutoIncrement(); result.setAutoIncrement(SqlHelper.VALUE_AUTO_INCREMENT_YES.equals(column.get(autoIncrement))); diff --git a/src/main/java/space/caoshd/otone/builder/SourceBuilder.java b/src/main/java/space/caoshd/otone/builder/SourceBuilder.java index aa145df..227c876 100644 --- a/src/main/java/space/caoshd/otone/builder/SourceBuilder.java +++ b/src/main/java/space/caoshd/otone/builder/SourceBuilder.java @@ -123,6 +123,8 @@ public class SourceBuilder { } private Map loadExtra(String tableName) { + extra.put("apiPrefix", CfgUtils.getProjectApiPrefix()); + extra.put("moduleName", CfgUtils.getModuleName()); extra.put("mapperPackageName", CfgUtils.getMapperPackageName()); extra.put("entityPackageName", CfgUtils.getEntityPackageName()); extra.put("resPackageName", CfgUtils.getResPackageName()); @@ -142,9 +144,11 @@ public class SourceBuilder { extra.put("reqNameSuffix", CfgUtils.getReqNameSuffix()); extra.put("queryNameSuffix", CfgUtils.getQueryNameSuffix()); extra.put("mybatisMapperEnable", CfgUtils.mybatisMapperEnable()); + String tableNameWithoutPrefix = getTableNameWithoutPrefix(tableName); - extra.put("ClassName", StrUtils.toCamelCase(tableNameWithoutPrefix, true)); - extra.put("className", StrUtils.toCamelCase(tableNameWithoutPrefix, false)); + extra.put("ClassName", StrUtils.snakeToPascalCase(tableNameWithoutPrefix)); + extra.put("className", StrUtils.snakeToCamelCase(tableNameWithoutPrefix)); + extra.put("urlName", StrUtils.snakeToKebabCase(tableNameWithoutPrefix)); return extra; } @@ -152,9 +156,9 @@ public class SourceBuilder { private String getTableNameWithoutPrefix(String tableNameWithoutPrefix) { List tablePrefixes = CONFIG.getStringList(CfgUtils.DATABASE_TABLE_PREFIXES); for (String tablePrefix : tablePrefixes) { - tableNameWithoutPrefix = StrUtils.removePrefix(tableNameWithoutPrefix, tablePrefix); + tableNameWithoutPrefix = StrUtils.removePrefixCaseIgnore(tableNameWithoutPrefix, tablePrefix); } - return tableNameWithoutPrefix; + return tableNameWithoutPrefix.toLowerCase(); } private void build(TableInfo tableInfo, List outputInfoList) { diff --git a/src/main/java/space/caoshd/otone/builder/TableBuilder.java b/src/main/java/space/caoshd/otone/builder/TableBuilder.java index 4805056..9edaaf6 100644 --- a/src/main/java/space/caoshd/otone/builder/TableBuilder.java +++ b/src/main/java/space/caoshd/otone/builder/TableBuilder.java @@ -8,7 +8,6 @@ import space.caoshd.otone.helper.SqlHelper; import space.caoshd.otone.util.CfgUtils; import space.caoshd.otone.util.DBUtils; import space.caoshd.otone.util.JsonUtils; -import space.caoshd.otone.util.TypeUtils; import java.util.ArrayList; import java.util.List; @@ -55,11 +54,8 @@ public class TableBuilder { List columnInfo = loadColumnInfo(tableSchema, tableName); result.setColumns(columnInfo); - result.setDateExists(columnInfo.stream() - .anyMatch(column -> TypeUtils.JAVA_TYPE_DATE.equals(column.getJavaType()))); - - result.setDecimalExists(columnInfo.stream() - .anyMatch(column -> TypeUtils.JAVA_TYPE_DECIMAL.equals(column.getJavaType()))); + result.setDateExists(columnInfo.stream().anyMatch(ColumnInfo::getDateType)); + result.setDecimalExists(columnInfo.stream().anyMatch(ColumnInfo::getDecimalType)); String invalidColumn = columnInfo.stream() .map(ColumnInfo::getColumnName) diff --git a/src/main/java/space/caoshd/otone/entity/ColumnInfo.java b/src/main/java/space/caoshd/otone/entity/ColumnInfo.java index 9eda9c0..f18877f 100644 --- a/src/main/java/space/caoshd/otone/entity/ColumnInfo.java +++ b/src/main/java/space/caoshd/otone/entity/ColumnInfo.java @@ -10,6 +10,8 @@ public class ColumnInfo { private String comment; private Boolean autoIncrement; private Boolean primary; + private Boolean dateType; + private Boolean decimalType; public String getColumnName() { return columnName; @@ -75,4 +77,19 @@ public class ColumnInfo { this.primary = primary; } + public Boolean getDateType() { + return dateType; + } + + public void setDateType(Boolean dateType) { + this.dateType = dateType; + } + + public Boolean getDecimalType() { + return decimalType; + } + + public void setDecimalType(Boolean decimalType) { + this.decimalType = decimalType; + } } diff --git a/src/main/java/space/caoshd/otone/util/CfgUtils.java b/src/main/java/space/caoshd/otone/util/CfgUtils.java index ade6604..5817415 100644 --- a/src/main/java/space/caoshd/otone/util/CfgUtils.java +++ b/src/main/java/space/caoshd/otone/util/CfgUtils.java @@ -21,6 +21,7 @@ public class CfgUtils { // 项目配置 public static final String PROJECT_PATH_BASE = "project.path.base"; public static final String PROJECT_PATH_JAVA = "project.path.java"; + public static final String PROJECT_API_PREFIX = "project.api.prefix"; public static final String PROJECT_PATH_RESOURCES = "project.path.resources"; // 包配置 @@ -115,6 +116,10 @@ public class CfgUtils { // 私有化构造器 private CfgUtils() {} + public static String getProjectApiPrefix() { + return CONFIG.getString(PROJECT_API_PREFIX); + } + public static String getDatabaseType() { return CONFIG.getString(DATABASE_TYPE); } @@ -132,6 +137,10 @@ public class CfgUtils { return CONFIG.getString(PROJECT_PATH_BASE).replaceAll("\\\\", "/"); } + public static String getModuleName() { + return StrUtils.getSuffix(getProjectBasePath(), "/"); + } + public static Boolean mybatisMapperEnable() { return CONFIG.getBoolean(OUTPUT_MYBATIS_MAPPER, Boolean.TRUE); } @@ -218,7 +227,7 @@ public class CfgUtils { } public static String getControllerPackageName() { - String moduleName = getServiceModuleName(); + String moduleName = getControllerModuleName(); String packageName = CONFIG.getString( PACKAGE_NAME_CONTROLLER, DEFAULT_PACKAGE_NAME_CONTROLLER diff --git a/src/main/java/space/caoshd/otone/util/StrUtils.java b/src/main/java/space/caoshd/otone/util/StrUtils.java index 62a8007..9e839ae 100644 --- a/src/main/java/space/caoshd/otone/util/StrUtils.java +++ b/src/main/java/space/caoshd/otone/util/StrUtils.java @@ -14,7 +14,7 @@ public class StrUtils { return split.length >= 1 ? split[0] : ""; } - public static String removePrefix(String str, String prefix) { + public static String removePrefixCaseIgnore(String str, String prefix) { if (str.toLowerCase().startsWith(prefix)) { return str.substring(prefix.length()); } else { @@ -22,8 +22,8 @@ public class StrUtils { } } - public static String removeSuffix(String str, String suffix) { - if (str.endsWith(suffix)) { + public static String removeSuffixCaseIgnore(String str, String suffix) { + if (str.toLowerCase().endsWith(suffix)) { return str.substring(0, str.length() - suffix.length()); } else { return str; @@ -37,24 +37,79 @@ public class StrUtils { return str; } - public static String toCamelCase(String str, boolean capitalizeFirstLetter) { - String lowerCaseStr = str.toLowerCase(); - StringBuilder sb = new StringBuilder(); - boolean upperCase = capitalizeFirstLetter; - for (int i = 0; i < lowerCaseStr.length(); i++) { - char c = lowerCaseStr.charAt(i); - if (c == '_') { - upperCase = true; - } else { - if (upperCase) { - sb.append(Character.toUpperCase(c)); - upperCase = false; - } else { - sb.append(c); + public static String snakeToCamelCase(String snakeCase) { + if (snakeCase == null || snakeCase.isEmpty()) { + return snakeCase; + } + + // 将字符串首字母转为小写,然后按下划线分割成数组 + String[] parts = snakeCase.toLowerCase().split("_"); + + // 初始化结果字符串,并将第一个单词的首字母转为小写 + StringBuilder camelCase = new StringBuilder(parts[0]); + + // 从第二个单词开始遍历数组,将每个单词的首字母大写并拼接到结果字符串中 + for (int i = 1; i < parts.length; i++) { + String part = parts[i]; + if (!part.isEmpty()) { + camelCase.append(Character.toUpperCase(part.charAt(0))); + camelCase.append(part.substring(1)); + } + } + + // 返回转换后的驼峰命名字符串 + return camelCase.toString(); + } + + public static String snakeToPascalCase(String snakeCase) { + if (snakeCase == null || snakeCase.isEmpty()) { + return snakeCase; + } + + // 将字符串首字母转为大写,其余部分转为小写,并按下划线分割成数组 + String[] parts = snakeCase.toLowerCase().split("_"); + + // 创建一个 StringBuilder 对象来构建结果字符串 + StringBuilder pascalCase = new StringBuilder(); + + // 遍历分割后的数组,将每个部分的首字母大写并拼接到结果字符串中 + for (String part : parts) { + if (part.isEmpty()) continue; // 跳过空字符串部分 + pascalCase.append(Character.toUpperCase(part.charAt(0))); + if (part.length() > 1) { + pascalCase.append(part.substring(1)); + } + } + + // 返回转换后的大驼峰命名字符串 + return pascalCase.toString(); + } + + public static String camelToKebabCase(String camelCase) { + StringBuilder result = new StringBuilder(); + boolean isPreviousUpperCase = false; + for (int i = 0; i < camelCase.length(); i++) { + char currentChar = camelCase.charAt(i); + if (Character.isUpperCase(currentChar)) { + if (i != 0 && !isPreviousUpperCase) { + result.append("-"); } + result.append(Character.toLowerCase(currentChar)); + isPreviousUpperCase = true; + } else { + result.append(currentChar); + isPreviousUpperCase = false; } } - return sb.toString(); + return result.toString(); + } + + public static String snakeToKebabCase(String snakeCase) { + if (snakeCase == null || snakeCase.isEmpty()) { + return snakeCase; + } + // 将下划线替换为连字符 + return snakeCase.replace("_", "-"); } } diff --git a/src/main/java/space/caoshd/otone/util/TypeUtils.java b/src/main/java/space/caoshd/otone/util/TypeUtils.java index d8a040b..ae16742 100644 --- a/src/main/java/space/caoshd/otone/util/TypeUtils.java +++ b/src/main/java/space/caoshd/otone/util/TypeUtils.java @@ -58,4 +58,11 @@ public class TypeUtils { throw new RuntimeException("unknown sql type:" + sqlType); } + public static Boolean isDecimalType(String javaType) { + return JAVA_TYPE_DECIMAL.equals(javaType); + } + + public static Boolean isDateType(String javaType) { + return JAVA_TYPE_DATE.equals(javaType); + } } diff --git a/src/test/java/space/caoshd/otone/builder/SourceBuilderTest.java b/src/test/java/space/caoshd/otone/builder/SourceBuilderTest.java index e8453b4..9100665 100644 --- a/src/test/java/space/caoshd/otone/builder/SourceBuilderTest.java +++ b/src/test/java/space/caoshd/otone/builder/SourceBuilderTest.java @@ -1,13 +1,9 @@ package space.caoshd.otone.builder; import org.junit.Test; -import space.caoshd.otone.helper.PropHelper; -import space.caoshd.otone.util.PathConsts; public class SourceBuilderTest { - private static final PropHelper CONFIG = new PropHelper(PathConsts.MYSQL_PROPERTIES_PATH); - @Test public void build() { new SourceBuilder() diff --git a/src/test/java/space/caoshd/otone/util/StrUtilsTest.java b/src/test/java/space/caoshd/otone/util/StrUtilsTest.java index d4a001c..8ada116 100644 --- a/src/test/java/space/caoshd/otone/util/StrUtilsTest.java +++ b/src/test/java/space/caoshd/otone/util/StrUtilsTest.java @@ -15,16 +15,18 @@ public class StrUtilsTest { @Test public void removePrefix() { - String username = StrUtils.removePrefix("t_user_name", "t_"); + String username = StrUtils.removePrefixCaseIgnore("t_user_name", "t_"); System.out.println(username); } @Test public void toCamelCase() { - String userName = StrUtils.toCamelCase("user_name", false); - String className = StrUtils.toCamelCase("class_name", true); + String userName = StrUtils.snakeToCamelCase("user_name"); + String className = StrUtils.snakeToPascalCase("class_name"); + String class_name = StrUtils.camelToKebabCase("userName"); System.out.println(userName); System.out.println(className); + System.out.println(class_name); } } \ No newline at end of file diff --git a/src/test/resources/config/config.properties b/src/test/resources/config/config.properties index bff7cf5..626c84d 100644 --- a/src/test/resources/config/config.properties +++ b/src/test/resources/config/config.properties @@ -1,4 +1,4 @@ -project.path.base=D:/workspace/otono-debug/ +project.path.base=D:/workspace/otono-debug package.name.base=space.caoshd.navigator database.type=h2 database.table.includes= @@ -7,6 +7,7 @@ output.cover_if_exists=true #project.path.java=src/main/java #project.path.resources=src/main/resources +project.api.prefix=/api/v1 #package.name.entity=repository.entity #package.name.mapper=repository.mapper #package.name.service.impl=service.impl diff --git a/src/test/resources/config/datasource.properties b/src/test/resources/config/datasource.properties index 03defdf..ae2a596 100644 --- a/src/test/resources/config/datasource.properties +++ b/src/test/resources/config/datasource.properties @@ -2,4 +2,4 @@ username=root password=otone@132! #url=jdbc:mysql://121.43.48.195:3306/otone?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai url=jdbc:h2:~/h2db/otone -driver-class-name=com.mysql.cj.jdbc.Driver \ No newline at end of file +driver-class-name=org.h2.Driver \ No newline at end of file diff --git a/src/test/resources/template/controller.vm b/src/test/resources/template/controller.vm index 2f3c50a..6327870 100644 --- a/src/test/resources/template/controller.vm +++ b/src/test/resources/template/controller.vm @@ -18,6 +18,9 @@ package ${ext.controllerPackageName}; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import ${ext.reqPackageName}.${ReqName}; import ${ext.resPackageName}.${ResName}; @@ -32,6 +35,7 @@ import java.util.stream.Collectors; * ${authorComment}${versionComment} */ @RestController +@RequestMapping("${ext.apiPrefix}/${ext.moduleName}/${ext.urlName}") public class ${ClassName} { @Autowired @@ -43,6 +47,7 @@ public class ${ClassName} { * @param req 主键为空-新增实体、主键非空-更新条件 * @return 影响记录数 */ + @PostMapping("/update-insert") Integer updateInsert(${ReqName} req){ return ${serviceName}.updateInsert(req); } @@ -53,6 +58,7 @@ public class ${ClassName} { * @param reqs 主键为空-新增实体、主键非空-更新条件 * @return 影响记录数 */ + @PostMapping("/update-insert-batch") Integer updateInsertBatch(List<${ReqName}> reqs) { return ${serviceName}.updateInsertBatch(reqs); } @@ -63,6 +69,7 @@ public class ${ClassName} { * @param req 删除条件 * @return 影响记录数 */ + @PostMapping("/delete") Integer delete(${ReqName} req) { return ${serviceName}.delete(req); } @@ -74,6 +81,7 @@ public class ${ClassName} { * @param req 删除条件 * @return 影响记录数 */ + @PostMapping("/invalid") Integer invalid(${ReqName} req) { return ${serviceName}.invalid(req); } @@ -85,6 +93,7 @@ public class ${ClassName} { * @param req 查询条件 * @return 单个 */ + @GetMapping("/any") ${ResName} anyOne(${ReqName} req) { ${EntityName} entity = ${serviceName}.anyOne(req); ${ResName} res = new ${ResName}(); @@ -98,6 +107,7 @@ public class ${ClassName} { * @param req 查询条件 * @return 单个 */ + @GetMapping("/only") ${ResName} onlyOne(${ReqName} req) { ${EntityName} entity = ${serviceName}.onlyOne(req); ${ResName} res = new ${ResName}(); @@ -111,6 +121,7 @@ public class ${ClassName} { * @param req 查询条件 * @return 列表 */ + @GetMapping("/list") List<${ResName}> list(${ReqName} req) { List<${EntityName} > entities = ${serviceName}.list(req); return entities.stream().map(entity -> { @@ -126,6 +137,7 @@ public class ${ClassName} { * @param req 查询条件 * @return 统计结果 */ + @GetMapping("/count") Long count(${ReqName} req) { return ${serviceName}.count(req); } diff --git a/src/test/resources/template/req.vm b/src/test/resources/template/req.vm index 867b8f5..c6846be 100644 --- a/src/test/resources/template/req.vm +++ b/src/test/resources/template/req.vm @@ -10,10 +10,44 @@ #end #set(${ClassName}="${ext.ClassName}$!{ext.reqNameSuffix}") package ${ext.reqPackageName}; +#if(${tbl.decimalExists}) +import java.math.BigDecimal; +#end +#if(${tbl.dateExists}) +import java.util.Date; +#end /** * $!{tbl.comment}表单提交 * ${authorComment}${versionComment} */ public class ${ClassName} { + +#foreach($column in ${tbl.columns}) + /** + * ${column.comment} + */ + private ${column.javaType} ${column.fieldName}; + +#end +#foreach($column in ${tbl.columns}) + /** + * 获取${column.comment} + * + * @return ${column.comment} + */ + public ${column.javaType} get${column.fieldNameCap}() { + return ${column.fieldName}; + } + + /** + * 设置${column.comment} + * + * @param ${column.fieldName} ${column.comment} + */ + public void set${column.fieldNameCap}(${column.javaType} ${column.fieldName}) { + this.${column.fieldName} = ${column.fieldName}; + } + +#end } \ No newline at end of file diff --git a/src/test/resources/template/res.vm b/src/test/resources/template/res.vm index e9c6a96..6e55d0b 100644 --- a/src/test/resources/template/res.vm +++ b/src/test/resources/template/res.vm @@ -10,6 +10,13 @@ #end #set(${ClassName}="${ext.ClassName}$!{ext.resNameSuffix}") package ${ext.resPackageName}; +#if(${tbl.decimalExists}) +import java.math.BigDecimal; +#end +#if(${tbl.dateExists}) +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +#end /** * $!{tbl.comment}视图 @@ -17,4 +24,34 @@ package ${ext.resPackageName}; */ public class ${ClassName} { +#foreach($column in ${tbl.columns}) + /** + * ${column.comment} + */ +#if(${column.dateType}) + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") +#end + private ${column.javaType} ${column.fieldName}; + +#end +#foreach($column in ${tbl.columns}) + /** + * 获取${column.comment} + * + * @return ${column.comment} + */ + public ${column.javaType} get${column.fieldNameCap}() { + return ${column.fieldName}; + } + + /** + * 设置${column.comment} + * + * @param ${column.fieldName} ${column.comment} + */ + public void set${column.fieldNameCap}(${column.javaType} ${column.fieldName}) { + this.${column.fieldName} = ${column.fieldName}; + } + +#end } \ No newline at end of file