| 2024.12.23 | 新增InsertSQL模式,采用JSQLParser引擎进行封装<br>优化代码封装<br>CDN恢复为staticfile.org加速(如果本地卡的话,建议切换local模式)。<br>

This commit is contained in:
Moshow郑锴 2024-12-23 16:06:36 +08:00
parent ea4e612445
commit 1a6e1a3ffb
19 changed files with 778 additions and 650 deletions

View File

@ -10,30 +10,31 @@
>powered by `Moshow郑锴(大狼狗)` , [https://zhengkai.blog.csdn.net](https://zhengkai.blog.csdn.net) >powered by `Moshow郑锴(大狼狗)` , [https://zhengkai.blog.csdn.net](https://zhengkai.blog.csdn.net)
# Description # Description
>Based on SpringBoot2+Freemarker<br> >The `Spring Boot Code Generator` , Based on SpringBoot3 and Freemarker<br>
> #基于`SpringBoot2`和`Freemarker`的代码生成平台 > #基于`SpringBoot3`和`Freemarker`的代码生成平台
> >
>For reducing the repetitive CRUD work<br> >Release your hands from tedious and repetitive CRUD tasks.<br>
> #以解放双手为目的,减少大量的`重复CRUD工作` > #从繁琐重复的`CRUD工作`中释放你的双手
> >
>Support mysql, oracle and pgsql<br> >Support mysql+oracle+pgsql , the most popular databases standard SQL<br>
> #支持`MySQL`、Oracle、PgSQL三大主流数据库 > #支持`MySQL`、Oracle、PgSQL三大主流数据库
> >
>Generate to many predefined popular templates by DDL-SQL/Insert-SQL/Simple JSON<br> >Generate various templates through table creation DDL statements, Insert SQL statements, Select SQL statements(*New), and simple JSON.<br>
> 可通过`建表SQL语句``INSERT语句`或者`简单JSON`生成预设的`JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper`相关模板代码. > 通过建表DDL语句、插入SQL语句、选择SQL语句*新以及简单JSON生成各种模板`JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper`.
> >
>Thanks for your using and feedback,I'm inspired by the 1500+PV (AVG) every day and github more than 1.9K stars <br> >Thank you all for your use and feedback. The daily PV visits of 1.5k in BeJSON and 2K Stars on GitHub are the greatest encouragement and motivation. <br>
> 感谢大家的使用和反馈每天1500的PV和获得超过九百多的星星是我前进和继续做下去的动力。 > 感谢大家的使用与反馈BeJSON上每天1.5K的PV访问量👀和 Github上2K的✨Stars是最大的鼓励与动力。
> >
>Hope everyone can keep good balance on work and life , stay health and safety . I wish you success in your new position and get promoted step by step. <br> >May everyone maintain a work-life balance, stay healthy and safe. Wishing you all success in your work and continuous advancements!. <br>
> 愿大家可以维持生活和工作平衡,保持健康和安全,祝大家工作顺利,步步高升! > 愿大家可以维持生活和工作平衡,保持健康和安全,祝大家工作顺利,步步高升!
>Please submit your issue and template , or pull your good idea into the PR <br> >
> 提交你的问题和生成模板或者提交你的好主意到PR。 >Welcome to submit your issue and useful templates , or put your good idea into PR <br>
> 欢迎提交你的问题和常用有用模板或者提交你的好主意到PR。
# URL # URL
- 感谢`卡卡`将他部署在[BEJSON](https://java.bejson.com/generator)上,目前是besjon专供的`金牌工具`(线上版本不一定是最新的,会有延迟,请谅解,谢谢).<br> - 感谢`卡卡`将他部署在[BEJSON](https://java.bejson.com/generator)上,目前是BeJSON专供的`金牌工具`(线上版本不一定是最新的,会有延迟,请谅解,谢谢).<br>
- 感谢`jully.top`部署的副本 [https://jully.top/generator/](https://jully.top/generator/)。<br> - 感谢`jully.top`部署的副本 [https://jully.top/generator/](https://jully.top/generator/)。<br>
- 感谢`BootCDN`提供稳定、快速、免费的前端开源项目 CDN 加速服务 - 感谢`BootCDN`提供稳定、快速、免费的前端开源项目 CDN 加速服务
- Thanks for `JetBrains` providing us the `Licenses for Open Source Development` [Get free access to all JetBrains tools for developing your open source project!](https://www.jetbrains.com/community/opensource/#support) .<br> - Thanks for `JetBrains` providing us the `Licenses for Open Source Development` [Get free access to all JetBrains tools for developing your open source project!](https://www.jetbrains.com/community/opensource/#support) .<br>
@ -49,7 +50,7 @@
| GITHUB仓库 | https://github.com/moshowgame/SpringBootCodeGenerator | | GITHUB仓库 | https://github.com/moshowgame/SpringBootCodeGenerator |
# Tips or Features # Tips or Features
- 支持`DDL SQL`/`INSERT SQL`/`SIMPLE JSON`种生成模式 - 支持`DDL SQL`/`INSERT SQL`/`SIMPLE JSON`/`SELECT SQL`(*New)四种生成模式
- `自动记忆`最近生成的内容最多保留9个 - `自动记忆`最近生成的内容最多保留9个
- 提供众多`通用模板`易于使用复制粘贴加简单修改即可完成CRUD操作 - 提供众多`通用模板`易于使用复制粘贴加简单修改即可完成CRUD操作
- 支持`特殊字符`模板(`#`请用`井`代替;`$`请用`¥`代替) - 支持`特殊字符`模板(`#`请用`井`代替;`$`请用`¥`代替)
@ -72,11 +73,12 @@
# Update Logs # Update Logs
| 更新日期 | 更新内容 | | 更新日期 | 更新内容 |
|:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 2024.04.23 | 切换为更快更稳定的BootCDN进行加速。<br>前端NEWUI改版基于AdminLTE+Bootstrap+Vue+ElementUI混合模式。| | 2024.12.23 | 新增InsertSQL模式采用JSQLParser引擎进行封装<br>优化代码封装<br>CDN恢复为staticfile.org加速(如果本地卡的话建议切换local模式)。<br> |
| 2024.04.22 | [Java CI with Maven](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml) 更新<br>SpringBoot升级到3.2.5<br>FastJSON升级到FastJSON2.0.49| | 2024.04.23 | 切换为更快更稳定的BootCDN进行加速。<br>前端NEWUI改版基于AdminLTE+Bootstrap+Vue+ElementUI混合模式。 |
| 2024.04.21 | 推出JDK11分支支持JDK8/JDK11/JDK17等版本兼容性较好但维护速度较慢为了更好兼容旧机器和旧环境| | 2024.04.22 | [Java CI with Maven](https://github.com/moshowgame/SpringBootCodeGenerator/actions/workflows/maven.yml) 更新<br>SpringBoot升级到3.2.5<br>FastJSON升级到FastJSON2.0.49 |
| 2024.04.20 | 修复CDN版本cdn.staticfile.org域名备份失败问题已同步更新到cdn.staticfile.net本地版本则不受影响| | 2024.04.21 | 推出JDK11分支支持JDK8/JDK11/JDK17等版本兼容性较好但维护速度较慢为了更好兼容旧机器和旧环境 |
| 2024.01.26 | 修复大写下滑线列名转驼峰问题(感谢@Nisus-Liu的PR| | 2024.04.20 | 修复CDN版本cdn.staticfile.org域名备份失败问题已同步更新到cdn.staticfile.net本地版本则不受影响 |
| 2024.01.26 | 修复大写下滑线列名转驼峰问题(感谢@Nisus-Liu的PR |
| 2023.10.22 | 工具站CDN更新。 | | 2023.10.22 | 工具站CDN更新。 |
| 2023.08.31 | (感谢@Nisus-Liu的PR<br>fix 驼峰列名转命名风格错误问题<br>增强转下划线命名风格, 对原始风格不敏感. 支持各种命名风格的列名 to 下划线<br>增加 NonCaseString 大小写不敏感字符串包装类, 简化编码<br>几点代码小优化。 | | 2023.08.31 | (感谢@Nisus-Liu的PR<br>fix 驼峰列名转命名风格错误问题<br>增强转下划线命名风格, 对原始风格不敏感. 支持各种命名风格的列名 to 下划线<br>增加 NonCaseString 大小写不敏感字符串包装类, 简化编码<br>几点代码小优化。 |
| 2023.07.11 | 安全更新正式支持SpringBoot3javax升级到jakarta。 | | 2023.07.11 | 安全更新正式支持SpringBoot3javax升级到jakarta。 |
@ -181,6 +183,8 @@
- 当项目从2.7.x的springboot升级到3.0.x的时候遇到一个问题“java: 程序包javax.servlet.http不存在” 问题: - 当项目从2.7.x的springboot升级到3.0.x的时候遇到一个问题“java: 程序包javax.servlet.http不存在” 问题:
[java: 程序包javax.servlet.http不存在](https://zhengkai.blog.csdn.net/article/details/131362304) [java: 程序包javax.servlet.http不存在](https://zhengkai.blog.csdn.net/article/details/131362304)
- [CSDN【SpringBoot2启示录】专栏](https://blog.csdn.net/moshowgame/category_9274885.html)
2024 NEWUI版本 2024 NEWUI版本
<img src="./newui_version.png"> <img src="./newui_version.png">
2021 半Vue半JS版本 2021 半Vue半JS版本

View File

@ -46,7 +46,13 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId> <artifactId>spring-boot-autoconfigure</artifactId>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build> <build>

View File

@ -8,6 +8,8 @@ import com.softdev.system.generator.util.MapUtil;
import com.softdev.system.generator.util.TableParseUtil; import com.softdev.system.generator.util.TableParseUtil;
import com.softdev.system.generator.util.ValueUtil; import com.softdev.system.generator.util.ValueUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -56,26 +58,36 @@ public class GeneratorController {
if (StringUtils.isEmpty(paramInfo.getTableSql())) { if (StringUtils.isEmpty(paramInfo.getTableSql())) {
return ReturnT.error("表结构信息为空"); return ReturnT.error("表结构信息为空");
} }
//1.Parse Table Structure 表结构解析 //1.Parse Table Structure 表结构解析
ClassInfo classInfo = null; ClassInfo classInfo = null;
String dataType = MapUtil.getString(paramInfo.getOptions(),"dataType"); String dataType = MapUtil.getString(paramInfo.getOptions(),"dataType");
if ("sql".equals(dataType)||dataType==null) { switch (dataType) {
classInfo = TableParseUtil.processTableIntoClassInfo(paramInfo); case "sql":
}else if ("json".equals(dataType)) { //默认模式parse DDL table structure from sql
//JSON模式parse field from json string classInfo = generatorService.processTableIntoClassInfo(paramInfo);
classInfo = TableParseUtil.processJsonToClassInfo(paramInfo); break;
//INSERT SQL模式parse field from insert sql case "json":
} else if ("insert-sql".equals(dataType)) { //JSON模式parse field from json string
classInfo = TableParseUtil.processInsertSqlToClassInfo(paramInfo); classInfo = generatorService.processJsonToClassInfo(paramInfo);
//正则表达式模式非完善版本parse sql by regex break;
} else if ("sql-regex".equals(dataType)) { case "insert-sql":
classInfo = TableParseUtil.processTableToClassInfoByRegex(paramInfo); //INSERT SQL模式parse field from insert sql
//默认模式default parse sql by java classInfo = generatorService.processInsertSqlToClassInfo(paramInfo);
break;
case "sql-regex":
//正则表达式模式非完善版本parse sql by regex
classInfo = generatorService.processTableToClassInfoByRegex(paramInfo);
break;
case "select-sql":
//SelectSqlBySQLPraser模式:parse select sql by JSqlParser
classInfo = generatorService.generateSelectSqlBySQLPraser(paramInfo);
break;
default:
//默认模式parse DDL table structure from sql
classInfo = generatorService.processTableIntoClassInfo(paramInfo);
break;
} }
//2.Set the params 设置表格参数 //2.Set the params 设置表格参数
paramInfo.getOptions().put("classInfo", classInfo); paramInfo.getOptions().put("classInfo", classInfo);
paramInfo.getOptions().put("tableName", classInfo == null ? System.currentTimeMillis() : classInfo.getTableName()); paramInfo.getOptions().put("tableName", classInfo == null ? System.currentTimeMillis() : classInfo.getTableName());

View File

@ -17,9 +17,9 @@ public class ParamInfo {
@Data @Data
public static class NAME_CASE_TYPE { public static class NAME_CASE_TYPE {
public static String CAMEL_CASE = "CamelCase"; public static final String CAMEL_CASE = "CamelCase";
public static String UNDER_SCORE_CASE = "UnderScoreCase"; public static final String UNDER_SCORE_CASE = "UnderScoreCase";
public static String UPPER_UNDER_SCORE_CASE = "UpperUnderScoreCase"; public static final String UPPER_UNDER_SCORE_CASE = "UpperUnderScoreCase";
} }
} }

View File

@ -1,5 +1,7 @@
package com.softdev.system.generator.service; package com.softdev.system.generator.service;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.ParamInfo;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -15,6 +17,40 @@ public interface GeneratorService {
String getTemplateConfig() throws IOException; String getTemplateConfig() throws IOException;
public Map<String, String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException; Map<String, String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException;
/**
* 解析Select-SQL生成类信息(JSQLPraser版本)
* @auther: zhengkai.blog.csdn.net
* @param paramInfo
* @return
*/
ClassInfo generateSelectSqlBySQLPraser(ParamInfo paramInfo) throws Exception;
/**
* 解析DDL-SQL生成类信息
* @auther: zhengkai.blog.csdn.net
* @param paramInfo
* @return
*/
ClassInfo processTableIntoClassInfo(ParamInfo paramInfo) throws Exception;
/**
* 解析JSON生成类信息
* @auther: zhengkai.blog.csdn.net
* @param paramInfo
* @return
*/
ClassInfo processJsonToClassInfo(ParamInfo paramInfo);
/**
* 解析DDL SQL生成类信息-正则表达式版本
* @auther: zhengkai.blog.csdn.net
* @param paramInfo
* @return
*/
ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo);
/**
* 解析INSERT-SQL生成类信息-正则表达式版本
* @auther: zhengkai.blog.csdn.net
* @param paramInfo
* @return
*/
ClassInfo processInsertSqlToClassInfo(ParamInfo paramInfo);
} }

View File

@ -3,22 +3,25 @@ package com.softdev.system.generator.service;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.softdev.system.generator.entity.TemplateConfig; import com.softdev.system.generator.entity.*;
import com.softdev.system.generator.util.FreemarkerUtil; import com.softdev.system.generator.util.*;
import com.softdev.system.generator.util.MapUtil;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectItem;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashMap; import java.util.concurrent.atomic.AtomicInteger;
import java.util.List; import java.util.regex.Matcher;
import java.util.Map; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -40,13 +43,10 @@ public class GeneratorServiceImpl implements GeneratorService {
@Override @Override
public String getTemplateConfig() throws IOException { public String getTemplateConfig() throws IOException {
templateCpnfig = null; templateCpnfig = null;
if (templateCpnfig != null) { InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template.json");
} else { templateCpnfig = new BufferedReader(new InputStreamReader(inputStream))
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template.json"); .lines().collect(Collectors.joining(System.lineSeparator()));
templateCpnfig = new BufferedReader(new InputStreamReader(inputStream)) inputStream.close();
.lines().collect(Collectors.joining(System.lineSeparator()));
inputStream.close();
}
//log.info(JSON.toJSONString(templateCpnfig)); //log.info(JSON.toJSONString(templateCpnfig));
return templateCpnfig; return templateCpnfig;
} }
@ -71,4 +71,515 @@ public class GeneratorServiceImpl implements GeneratorService {
return result; return result;
} }
/**
* 根据SQL解析器解析表结构
* @author zhengkai.blog.csdn.net
* @param paramInfo
* @return
* @throws Exception
*/
@Override
public ClassInfo generateSelectSqlBySQLPraser(ParamInfo paramInfo) throws Exception {
ClassInfo classInfo = new ClassInfo();
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(paramInfo.getTableSql());
List<SelectItem<?>> columnNameList = select.getSelectItems();
log.info("tableName:{}", select.getFromItem().toString());
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
columnNameList.forEach(t->{
FieldInfo fieldInfo = new FieldInfo();
String fieldName = ((Column)t.getExpression()).getColumnName();
String aliasName = t.getAlias() != null ? t.getAlias().getName() : ((Column)t.getExpression()).getColumnName();
//存储原始字段名
fieldInfo.setFieldComment(aliasName);fieldInfo.setColumnName(aliasName);
//处理字段名是t.xxx的情况
fieldName=fieldName.contains(".")?fieldName.substring(fieldName.indexOf(".")+1):fieldName;
//转换前
fieldInfo.setColumnName(fieldName);
switch ((String) paramInfo.getOptions().get("nameCaseType")) {
case ParamInfo.NAME_CASE_TYPE.CAMEL_CASE:
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰
fieldName = StringUtilsPlus.toLowerCamel(aliasName);
break;
case ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE:
fieldName = StringUtilsPlus.toUnderline(aliasName, false);
break;
case ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE:
fieldName = StringUtilsPlus.toUnderline(aliasName.toUpperCase(), true);
break;
default:
fieldName = aliasName;
break;
}
//转换后
fieldInfo.setFieldName(fieldName);
//无法推测类型所有都set为String
fieldInfo.setFieldClass("String");
fieldList.add(fieldInfo);
});
classInfo.setFieldList(fieldList);
String tableName = select.getFromItem().toString();
classInfo.setTableName(tableName);
//如果表名有空格取空格前的第一个单词作为类名
if(tableName.indexOf(" ")>0){
classInfo.setClassName(StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName.substring(0,tableName.indexOf(" ")))));
}else{
classInfo.setClassName(StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName)));
}
log.info("classInfo:{}", JSON.toJSONString(classInfo));
return classInfo;
}
/**
* 解析DDL SQL生成类信息(默认模式|核心模式)
*
* @param paramInfo
* @return
*/
@Override
public ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
throws IOException {
//process the param
NonCaseString tableSql = NonCaseString.of(paramInfo.getTableSql());
String nameCaseType = MapUtil.getString(paramInfo.getOptions(),"nameCaseType");
Boolean isPackageType = MapUtil.getBoolean(paramInfo.getOptions(),"isPackageType");
//更新空值处理
if (StringUtils.isBlank(tableSql)) {
throw new CodeGenerateException("Table structure can not be empty. 表结构不能为空。");
}
//deal with special character
tableSql = tableSql.trim()
.replaceAll("'", "`")
.replaceAll("\"", "`")
.replaceAll("", ",")
// 这里全部转小写, 会让驼峰风格的字段名丢失驼峰信息(真有驼峰sql字段名的呢(*)); 下文使用工具方法处理包含等
// .toLowerCase()
;
//deal with java string copy \n"
tableSql = tableSql.trim().replaceAll("\\\\n`", "").replaceAll("\\+", "").replaceAll("``", "`").replaceAll("\\\\", "");
// table Name
String tableName = null;
int tableKwIx = tableSql.indexOf("TABLE"); // 包含判断和位置一次搞定
if (tableKwIx > -1 && tableSql.contains("(")) {
tableName = tableSql.substring(tableKwIx + 5, tableSql.indexOf("(")).get();
} else {
throw new CodeGenerateException("Table structure incorrect.表结构不正确。");
}
//新增处理create table if not exists members情况
if (tableName.contains("if not exists")) {
tableName = tableName.replaceAll("if not exists", "");
}
if (tableName.contains("`")) {
tableName = tableName.substring(tableName.indexOf("`") + 1, tableName.lastIndexOf("`"));
} else {
//空格开头的需要替换掉\n\t空格
tableName = tableName.replaceAll(" ", "").replaceAll("\n", "").replaceAll("\t", "");
}
//优化对byeas`.`ct_bd_customerdiscount这种命名的支持
if (tableName.contains("`.`")) {
tableName = tableName.substring(tableName.indexOf("`.`") + 3);
} else if (tableName.contains(".")) {
//优化对likeu.members这种命名的支持
tableName = tableName.substring(tableName.indexOf(".") + 1);
}
String originTableName = tableName;
//ignore prefix
if(tableName!=null && StringUtilsPlus.isNotNull(MapUtil.getString(paramInfo.getOptions(),"ignorePrefix"))){
tableName = tableName.replaceAll(MapUtil.getString(paramInfo.getOptions(),"ignorePrefix"),"");
}
// class Name
String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName));
if (className.contains("_")) {
className = className.replaceAll("_", "");
}
// class Comment
String classComment = null;
//mysql是comment=,pgsql/oracle是comment on table,
//2020-05-25 优化表备注的获取逻辑
if (tableSql.containsAny("comment=", "comment on table")) {
int ix = tableSql.lastIndexOf("comment=");
String classCommentTmp = (ix > -1) ?
tableSql.substring(ix + 8).trim().get() :
tableSql.substring(tableSql.lastIndexOf("comment on table") + 17).trim().get();
if (classCommentTmp.contains("`")) {
classCommentTmp = classCommentTmp.substring(classCommentTmp.indexOf("`") + 1);
classCommentTmp = classCommentTmp.substring(0, classCommentTmp.indexOf("`"));
classComment = classCommentTmp;
} else {
//非常规的没法分析
classComment = className;
}
} else {
//修复表备注为空问题
classComment = tableName;
}
//如果备注跟;混在一起需要替换掉
classComment = classComment.replaceAll(";", "");
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
// 正常( ) 内的一定是字段相关的定义
String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")")).get();
// 匹配 comment替换备注里的小逗号, 防止不小心被当成切割符号切割
String commentPattenStr1 = "comment `(.*?)\\`";
Matcher matcher1 = Pattern.compile(commentPattenStr1).matcher(fieldListTmp);
while (matcher1.find()) {
String commentTmp = matcher1.group();
//2018-9-27 zhengk 不替换只处理支持COMMENT评论里面多种注释
//commentTmp = commentTmp.replaceAll("\\ comment `|\\`", " "); // "\\{|\\}"
if (commentTmp.contains(",")) {
String commentTmpFinal = commentTmp.replaceAll(",", "");
fieldListTmp = fieldListTmp.replace(matcher1.group(), commentTmpFinal);
}
}
//2018-10-18 zhengkai 新增支持double(10, 2)等类型中有英文逗号的特殊情况
String commentPattenStr2 = "\\`(.*?)\\`";
Matcher matcher2 = Pattern.compile(commentPattenStr2).matcher(fieldListTmp);
while (matcher2.find()) {
String commentTmp2 = matcher2.group();
if (commentTmp2.contains(",")) {
String commentTmpFinal = commentTmp2.replaceAll(",", "").replaceAll("\\(", "").replaceAll("\\)", "");
fieldListTmp = fieldListTmp.replace(matcher2.group(), commentTmpFinal);
}
}
//2018-10-18 zhengkai 新增支持double(10, 2)等类型中有英文逗号的特殊情况
String commentPattenStr3 = "\\((.*?)\\)";
Matcher matcher3 = Pattern.compile(commentPattenStr3).matcher(fieldListTmp);
while (matcher3.find()) {
String commentTmp3 = matcher3.group();
if (commentTmp3.contains(",")) {
String commentTmpFinal = commentTmp3.replaceAll(",", "");
fieldListTmp = fieldListTmp.replace(matcher3.group(), commentTmpFinal);
}
}
String[] fieldLineList = fieldListTmp.split(",");
if (fieldLineList.length > 0) {
int i = 0;
//i为了解决primary key关键字出现的地方出现在前3行一般和id有关
for (String columnLine0 : fieldLineList) {
NonCaseString columnLine = NonCaseString.of(columnLine0);
i++;
columnLine = columnLine.replaceAll("\n", "").replaceAll("\t", "").trim();
// `userid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
// 2018-9-18 zhengk 修改为contains提升匹配率和匹配不按照规矩出牌的语句
// 2018-11-8 zhengkai 修复tornadoorz反馈的KEY FK_permission_id (permission_id),KEY FK_role_id (role_id)情况
// 2019-2-22 zhengkai 要在条件中使用复杂的表达式
// 2019-4-29 zhengkai 优化对普通和特殊storage关键字的判断感谢@AhHeadFloating的反馈
// 2020-10-20 zhengkai 优化对fulltext/index关键字的处理感谢@WEGFan的反馈
// 2023-8-27 L&J 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
boolean notSpecialFlag = isNotSpecialColumnLine(columnLine, i);
if (notSpecialFlag) {
//如果是oracle的number(x,x)可能出现最后分割残留的,x)这里做排除处理
if (columnLine.length() < 5) {
continue;
}
//2018-9-16 zhengkai 支持'符号以及空格的oracle语句// userid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
String columnName = "";
columnLine = columnLine.replaceAll("`", " ").replaceAll("\"", " ").replaceAll("'", "").replaceAll(" ", " ").trim();
//如果遇到username varchar(65) default '' not null,这种情况判断第一个空格是否比第一个引号前
try {
columnName = columnLine.substring(0, columnLine.indexOf(" ")).get();
} catch (StringIndexOutOfBoundsException e) {
System.out.println("err happened: " + columnLine);
throw e;
}
// field Name
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
// 2023-8-27 L&J 支持原始列名任意命名风格, 不依赖用户是否输入下划线
String fieldName = null;
if (ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)) {
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰
fieldName = StringUtilsPlus.toLowerCamel(columnName);
} else if (ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE.equals(nameCaseType)) {
fieldName = StringUtilsPlus.toUnderline(columnName, false);
} else if (ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)) {
fieldName = StringUtilsPlus.toUnderline(columnName.toUpperCase(), true);
} else {
fieldName = columnName;
}
columnLine = columnLine.substring(columnLine.indexOf("`") + 1).trim();
String mysqlType = columnLine.split("\\s+")[1];
if(mysqlType.contains("(")){
mysqlType = mysqlType.substring(0, mysqlType.indexOf("("));
}
//swagger class
String swaggerClass = "string" ;
if(mysqlJavaTypeUtil.getMysqlSwaggerTypeMap().containsKey(mysqlType)){
swaggerClass = mysqlJavaTypeUtil.getMysqlSwaggerTypeMap().get(mysqlType);
}
// field class
// int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
String fieldClass = "String";
//2018-9-16 zhengk 补充char/clob/blob/json等类型如果类型未知默认为String
//2018-11-22 lshz0088 处理字段类型的时候不严谨columnLine.contains(" int") 类似这种的可在前后适当加一些空格之类的加以区分否则当我的字段包含这些字符的时候产生类型判断问题
//2020-05-03 MOSHOW.K.ZHENG 优化对所有类型的处理
//2020-10-20 zhengkai 新增包装类型的转换选择
if(mysqlJavaTypeUtil.getMysqlJavaTypeMap().containsKey(mysqlType)){
fieldClass = mysqlJavaTypeUtil.getMysqlJavaTypeMap().get(mysqlType);
}
// field commentMySQL的一般位于field行而pgsql和oralce多位于后面
String fieldComment = null;
if (tableSql.contains("comment on column") && (tableSql.contains("." + columnName + " is ") || tableSql.contains(".`" + columnName + "` is"))) {
//新增对pgsql/oracle的字段备注支持
//COMMENT ON COLUMN public.check_info.check_name IS '检查者名称';
//2018-11-22 lshz0088 正则表达式的点号前面应该加上两个反斜杠否则会认为是任意字符
//2019-4-29 zhengkai 优化对oracle注释comment on column的支持@liukex
tableSql = tableSql.replaceAll(".`" + columnName + "` is", "." + columnName + " is");
Matcher columnCommentMatcher = Pattern.compile("\\." + columnName + " is `").matcher(tableSql);
fieldComment = columnName;
while (columnCommentMatcher.find()) {
String columnCommentTmp = columnCommentMatcher.group();
//System.out.println(columnCommentTmp);
fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim().get();
fieldComment = fieldComment.substring(0, fieldComment.indexOf("`")).trim();
}
} else if (columnLine.contains(" comment")) {
//20200518 zhengkai 修复包含comment关键字的问题
String commentTmp = columnLine.substring(columnLine.lastIndexOf("comment") + 7).trim().get();
// '用户ID',
if (commentTmp.contains("`") || commentTmp.indexOf("`") != commentTmp.lastIndexOf("`")) {
commentTmp = commentTmp.substring(commentTmp.indexOf("`") + 1, commentTmp.lastIndexOf("`"));
}
//解决最后一句是评论无主键且连着)的问题:album_id int(3) default '1' null comment '相册id0 代表头像 1代表照片墙')
if (commentTmp.contains(")")) {
commentTmp = commentTmp.substring(0, commentTmp.lastIndexOf(")") + 1);
}
fieldComment = commentTmp;
} else {
//修复comment不存在导致报错的问题
fieldComment = columnName;
}
FieldInfo fieldInfo = new FieldInfo();
//
fieldInfo.setColumnName(columnName);
fieldInfo.setFieldName(fieldName);
fieldInfo.setFieldClass(fieldClass);
fieldInfo.setSwaggerClass(swaggerClass);
fieldInfo.setFieldComment(fieldComment);
fieldList.add(fieldInfo);
}
}
}
if (fieldList.size() < 1) {
throw new CodeGenerateException("表结构分析失败请检查语句或者提交issue给我");
}
ClassInfo codeJavaInfo = new ClassInfo();
codeJavaInfo.setTableName(tableName);
codeJavaInfo.setClassName(className);
codeJavaInfo.setClassComment(classComment);
codeJavaInfo.setFieldList(fieldList);
codeJavaInfo.setOriginTableName(originTableName);
return codeJavaInfo;
}
private static boolean isNotSpecialColumnLine(NonCaseString columnLine, int lineSeq) {
return (
!columnLine.containsAny(
"key ",
"constraint",
" using ",
"unique ",
"fulltext ",
"index ",
"pctincrease",
"buffer_pool",
"tablespace"
)
&& !(columnLine.contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
&& !(columnLine.contains("primary ") && lineSeq > 3)
);
}
/**
* 解析JSON生成类信息
*
* @param paramInfo
* @return
*/
@Override
public ClassInfo processJsonToClassInfo(ParamInfo paramInfo) {
ClassInfo codeJavaInfo = new ClassInfo();
codeJavaInfo.setTableName("JsonDto");
codeJavaInfo.setClassName("JsonDto");
codeJavaInfo.setClassComment("JsonDto");
//support children json if forget to add '{' in front of json
if (paramInfo.getTableSql().trim().startsWith("\"")) {
paramInfo.setTableSql("{" + paramInfo.getTableSql());
}
if (JSON.isValid(paramInfo.getTableSql())) {
if (paramInfo.getTableSql().trim().startsWith("{")) {
JSONObject jsonObject = JSONObject.parseObject(paramInfo.getTableSql().trim());
//parse FieldList by JSONObject
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonObject));
} else if (paramInfo.getTableSql().trim().startsWith("[")) {
JSONArray jsonArray = JSONArray.parseArray(paramInfo.getTableSql().trim());
//parse FieldList by JSONObject
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonArray.getJSONObject(0)));
}
}
return codeJavaInfo;
}
/**
* parse SQL by regex
*
* @param paramInfo
* @return
* @author https://github.com/ydq
*/
public ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo) {
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
//return classInfo
ClassInfo codeJavaInfo = new ClassInfo();
//匹配整个ddl将ddl分为表名列sql部分表注释
String DDL_PATTEN_STR = "\\s*create\\s+table\\s+(?<tableName>\\S+)[^\\(]*\\((?<columnsSQL>[\\s\\S]+)\\)[^\\)]+?(comment\\s*(=|on\\s+table)\\s*'(?<tableComment>.*?)'\\s*;?)?$";
Pattern DDL_PATTERN = Pattern.compile(DDL_PATTEN_STR, Pattern.CASE_INSENSITIVE);
//匹配列sql部分分别解析每一列的列名 类型 和列注释
String COL_PATTERN_STR = "\\s*(?<fieldName>\\S+)\\s+(?<fieldType>\\w+)\\s*(?:\\([\\s\\d,]+\\))?((?!comment).)*(comment\\s*'(?<fieldComment>.*?)')?\\s*(,|$)";
Pattern COL_PATTERN = Pattern.compile(COL_PATTERN_STR, Pattern.CASE_INSENSITIVE);
Matcher matcher = DDL_PATTERN.matcher(paramInfo.getTableSql().trim());
if (matcher.find()) {
String tableName = matcher.group("tableName");
String tableComment = matcher.group("tableComment");
codeJavaInfo.setTableName(tableName.replaceAll("'", ""));
codeJavaInfo.setClassName(tableName.replaceAll("'", ""));
codeJavaInfo.setClassComment(tableComment.replaceAll("'", ""));
String columnsSQL = matcher.group("columnsSQL");
if (columnsSQL != null && columnsSQL.length() > 0) {
Matcher colMatcher = COL_PATTERN.matcher(columnsSQL);
while (colMatcher.find()) {
String fieldName = colMatcher.group("fieldName");
String fieldType = colMatcher.group("fieldType");
String fieldComment = colMatcher.group("fieldComment");
if (!"key".equalsIgnoreCase(fieldType)) {
FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldName(fieldName.replaceAll("'", ""));
fieldInfo.setColumnName(fieldName.replaceAll("'", ""));
fieldInfo.setFieldClass(fieldType.replaceAll("'", ""));
fieldInfo.setFieldComment(fieldComment.replaceAll("'", ""));
fieldList.add(fieldInfo);
}
}
}
codeJavaInfo.setFieldList(fieldList);
}
return codeJavaInfo;
}
public List<FieldInfo> processJsonObjectToFieldList(JSONObject jsonObject) {
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
jsonObject.keySet().stream().forEach(jsonField -> {
FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldName(jsonField);
fieldInfo.setColumnName(jsonField);
fieldInfo.setFieldClass(String.class.getSimpleName());
fieldInfo.setFieldComment("father:" + jsonField);
fieldList.add(fieldInfo);
if (jsonObject.get(jsonField) instanceof JSONArray) {
jsonObject.getJSONArray(jsonField).stream().forEach(arrayObject -> {
FieldInfo fieldInfo2 = new FieldInfo();
fieldInfo2.setFieldName(arrayObject.toString());
fieldInfo2.setColumnName(arrayObject.toString());
fieldInfo2.setFieldClass(String.class.getSimpleName());
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
fieldList.add(fieldInfo2);
});
} else if (jsonObject.get(jsonField) instanceof JSONObject) {
jsonObject.getJSONObject(jsonField).keySet().stream().forEach(arrayObject -> {
FieldInfo fieldInfo2 = new FieldInfo();
fieldInfo2.setFieldName(arrayObject.toString());
fieldInfo2.setColumnName(arrayObject.toString());
fieldInfo2.setFieldClass(String.class.getSimpleName());
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
fieldList.add(fieldInfo2);
});
}
});
if (fieldList.size() < 1) {
throw new CodeGenerateException("JSON解析失败");
}
return fieldList;
}
public ClassInfo processInsertSqlToClassInfo(ParamInfo paramInfo) {
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
//return classInfo
ClassInfo codeJavaInfo = new ClassInfo();
//get origin sql
String fieldSqlStr = paramInfo.getTableSql().toLowerCase().trim();
fieldSqlStr = fieldSqlStr.replaceAll(" ", " ").replaceAll("\\\\n`", "")
.replaceAll("\\+", "").replaceAll("``", "`").replaceAll("\\\\", "");
String valueStr = fieldSqlStr.substring(fieldSqlStr.lastIndexOf("values") + 6).replaceAll(" ", "").replaceAll("\\(", "").replaceAll("\\)", "");
//get the string between insert into and values
fieldSqlStr = fieldSqlStr.substring(0, fieldSqlStr.lastIndexOf("values"));
System.out.println(fieldSqlStr);
String insertSqlPattenStr = "insert into (?<tableName>.*) \\((?<columnsSQL>.*)\\)";
//String DDL_PATTEN_STR="\\s*create\\s+table\\s+(?<tableName>\\S+)[^\\(]*\\((?<columnsSQL>[\\s\\S]+)\\)[^\\)]+?(comment\\s*(=|on\\s+table)\\s*'(?<tableComment>.*?)'\\s*;?)?$";
Matcher matcher1 = Pattern.compile(insertSqlPattenStr).matcher(fieldSqlStr);
while (matcher1.find()) {
String tableName = matcher1.group("tableName");
//System.out.println("tableName:"+tableName);
codeJavaInfo.setClassName(tableName);
codeJavaInfo.setTableName(tableName);
String columnsSQL = matcher1.group("columnsSQL");
//System.out.println("columnsSQL:"+columnsSQL);
List<String> valueList = new ArrayList<>();
//add values as comment
Arrays.stream(valueStr.split(",")).forEach(column -> {
valueList.add(column);
});
AtomicInteger n = new AtomicInteger(0);
//add column to fleldList
Arrays.stream(columnsSQL.replaceAll(" ", "").split(",")).forEach(column -> {
FieldInfo fieldInfo2 = new FieldInfo();
fieldInfo2.setFieldName(column);
fieldInfo2.setColumnName(column);
fieldInfo2.setFieldClass(String.class.getSimpleName());
if (n.get() < valueList.size()) {
fieldInfo2.setFieldComment(column + " , eg." + valueList.get(n.get()));
}
fieldList.add(fieldInfo2);
n.getAndIncrement();
});
}
if (fieldList.size() < 1) {
throw new CodeGenerateException("INSERT SQL解析失败");
}
codeJavaInfo.setFieldList(fieldList);
return codeJavaInfo;
}
} }

View File

@ -5,7 +5,7 @@ package com.softdev.system.generator.util;
* *
* @author xuxueli 2018-05-02 20:43:25 * @author xuxueli 2018-05-02 20:43:25
*/ */
public class StringUtils { public class StringUtilsPlus {
/** /**
* 首字母大写 * 首字母大写

View File

@ -23,452 +23,6 @@ import java.util.regex.Pattern;
*/ */
public class TableParseUtil { public class TableParseUtil {
/**
* 解析DDL SQL生成类信息
*
* @param paramInfo
* @return
*/
public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
throws IOException {
//process the param
NonCaseString tableSql = NonCaseString.of(paramInfo.getTableSql());
String nameCaseType = MapUtil.getString(paramInfo.getOptions(),"nameCaseType");
Boolean isPackageType = MapUtil.getBoolean(paramInfo.getOptions(),"isPackageType");
if (tableSql == null || tableSql.trim().length() == 0) {
throw new CodeGenerateException("Table structure can not be empty. 表结构不能为空。");
}
//deal with special character
tableSql = tableSql.trim()
.replaceAll("'", "`")
.replaceAll("\"", "`")
.replaceAll("", ",")
// 这里全部转小写, 会让驼峰风格的字段名丢失驼峰信息(真有驼峰sql字段名的呢(*)); 下文使用工具方法处理包含等
// .toLowerCase()
;
//deal with java string copy \n"
tableSql = tableSql.trim().replaceAll("\\\\n`", "").replaceAll("\\+", "").replaceAll("``", "`").replaceAll("\\\\", "");
// table Name
String tableName = null;
int tableKwIx = tableSql.indexOf("TABLE"); // 包含判断和位置一次搞定
if (tableKwIx > -1 && tableSql.contains("(")) {
tableName = tableSql.substring(tableKwIx + 5, tableSql.indexOf("(")).get();
} else {
throw new CodeGenerateException("Table structure incorrect.表结构不正确。");
}
//新增处理create table if not exists members情况
if (tableName.contains("if not exists")) {
tableName = tableName.replaceAll("if not exists", "");
}
if (tableName.contains("`")) {
tableName = tableName.substring(tableName.indexOf("`") + 1, tableName.lastIndexOf("`"));
} else {
//空格开头的需要替换掉\n\t空格
tableName = tableName.replaceAll(" ", "").replaceAll("\n", "").replaceAll("\t", "");
}
//优化对byeas`.`ct_bd_customerdiscount这种命名的支持
if (tableName.contains("`.`")) {
tableName = tableName.substring(tableName.indexOf("`.`") + 3);
} else if (tableName.contains(".")) {
//优化对likeu.members这种命名的支持
tableName = tableName.substring(tableName.indexOf(".") + 1);
}
String originTableName = tableName;
//ignore prefix
if(tableName!=null && StringUtils.isNotNull(MapUtil.getString(paramInfo.getOptions(),"ignorePrefix"))){
tableName = tableName.replaceAll(MapUtil.getString(paramInfo.getOptions(),"ignorePrefix"),"");
}
// class Name
String className = StringUtils.upperCaseFirst(StringUtils.underlineToCamelCase(tableName));
if (className.contains("_")) {
className = className.replaceAll("_", "");
}
// class Comment
String classComment = null;
//mysql是comment=,pgsql/oracle是comment on table,
//2020-05-25 优化表备注的获取逻辑
if (tableSql.containsAny("comment=", "comment on table")) {
int ix = tableSql.lastIndexOf("comment=");
String classCommentTmp = (ix > -1) ?
tableSql.substring(ix + 8).trim().get() :
tableSql.substring(tableSql.lastIndexOf("comment on table") + 17).trim().get();
if (classCommentTmp.contains("`")) {
classCommentTmp = classCommentTmp.substring(classCommentTmp.indexOf("`") + 1);
classCommentTmp = classCommentTmp.substring(0, classCommentTmp.indexOf("`"));
classComment = classCommentTmp;
} else {
//非常规的没法分析
classComment = className;
}
} else {
//修复表备注为空问题
classComment = tableName;
}
//如果备注跟;混在一起需要替换掉
classComment = classComment.replaceAll(";", "");
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
// 正常( ) 内的一定是字段相关的定义
String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")")).get();
// 匹配 comment替换备注里的小逗号, 防止不小心被当成切割符号切割
String commentPattenStr1 = "comment `(.*?)\\`";
Matcher matcher1 = Pattern.compile(commentPattenStr1).matcher(fieldListTmp);
while (matcher1.find()) {
String commentTmp = matcher1.group();
//2018-9-27 zhengk 不替换只处理支持COMMENT评论里面多种注释
//commentTmp = commentTmp.replaceAll("\\ comment `|\\`", " "); // "\\{|\\}"
if (commentTmp.contains(",")) {
String commentTmpFinal = commentTmp.replaceAll(",", "");
fieldListTmp = fieldListTmp.replace(matcher1.group(), commentTmpFinal);
}
}
//2018-10-18 zhengkai 新增支持double(10, 2)等类型中有英文逗号的特殊情况
String commentPattenStr2 = "\\`(.*?)\\`";
Matcher matcher2 = Pattern.compile(commentPattenStr2).matcher(fieldListTmp);
while (matcher2.find()) {
String commentTmp2 = matcher2.group();
if (commentTmp2.contains(",")) {
String commentTmpFinal = commentTmp2.replaceAll(",", "").replaceAll("\\(", "").replaceAll("\\)", "");
fieldListTmp = fieldListTmp.replace(matcher2.group(), commentTmpFinal);
}
}
//2018-10-18 zhengkai 新增支持double(10, 2)等类型中有英文逗号的特殊情况
String commentPattenStr3 = "\\((.*?)\\)";
Matcher matcher3 = Pattern.compile(commentPattenStr3).matcher(fieldListTmp);
while (matcher3.find()) {
String commentTmp3 = matcher3.group();
if (commentTmp3.contains(",")) {
String commentTmpFinal = commentTmp3.replaceAll(",", "");
fieldListTmp = fieldListTmp.replace(matcher3.group(), commentTmpFinal);
}
}
String[] fieldLineList = fieldListTmp.split(",");
if (fieldLineList.length > 0) {
int i = 0;
//i为了解决primary key关键字出现的地方出现在前3行一般和id有关
for (String columnLine0 : fieldLineList) {
NonCaseString columnLine = NonCaseString.of(columnLine0);
i++;
columnLine = columnLine.replaceAll("\n", "").replaceAll("\t", "").trim();
// `userid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
// 2018-9-18 zhengk 修改为contains提升匹配率和匹配不按照规矩出牌的语句
// 2018-11-8 zhengkai 修复tornadoorz反馈的KEY FK_permission_id (permission_id),KEY FK_role_id (role_id)情况
// 2019-2-22 zhengkai 要在条件中使用复杂的表达式
// 2019-4-29 zhengkai 优化对普通和特殊storage关键字的判断感谢@AhHeadFloating的反馈
// 2020-10-20 zhengkai 优化对fulltext/index关键字的处理感谢@WEGFan的反馈
// 2023-8-27 L&J 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
boolean notSpecialFlag = isNotSpecialColumnLine(columnLine, i);
if (notSpecialFlag) {
//如果是oracle的number(x,x)可能出现最后分割残留的,x)这里做排除处理
if (columnLine.length() < 5) {
continue;
}
//2018-9-16 zhengkai 支持'符号以及空格的oracle语句// userid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
String columnName = "";
columnLine = columnLine.replaceAll("`", " ").replaceAll("\"", " ").replaceAll("'", "").replaceAll(" ", " ").trim();
//如果遇到username varchar(65) default '' not null,这种情况判断第一个空格是否比第一个引号前
try {
columnName = columnLine.substring(0, columnLine.indexOf(" ")).get();
} catch (StringIndexOutOfBoundsException e) {
System.out.println("err happened: " + columnLine);
throw e;
}
// field Name
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
// 2023-8-27 L&J 支持原始列名任意命名风格, 不依赖用户是否输入下划线
String fieldName = null;
if (ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)) {
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰
fieldName = StringUtils.toLowerCamel(columnName);
} else if (ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE.equals(nameCaseType)) {
fieldName = StringUtils.toUnderline(columnName, false);
} else if (ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)) {
fieldName = StringUtils.toUnderline(columnName.toUpperCase(), true);
} else {
fieldName = columnName;
}
columnLine = columnLine.substring(columnLine.indexOf("`") + 1).trim();
String mysqlType = columnLine.split("\\s+")[1];
if(mysqlType.contains("(")){
mysqlType = mysqlType.substring(0, mysqlType.indexOf("("));
}
//swagger class
String swaggerClass = "string" ;
if(mysqlJavaTypeUtil.getMysqlSwaggerTypeMap().containsKey(mysqlType)){
swaggerClass = mysqlJavaTypeUtil.getMysqlSwaggerTypeMap().get(mysqlType);
}
// field class
// int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
String fieldClass = "String";
//2018-9-16 zhengk 补充char/clob/blob/json等类型如果类型未知默认为String
//2018-11-22 lshz0088 处理字段类型的时候不严谨columnLine.contains(" int") 类似这种的可在前后适当加一些空格之类的加以区分否则当我的字段包含这些字符的时候产生类型判断问题
//2020-05-03 MOSHOW.K.ZHENG 优化对所有类型的处理
//2020-10-20 zhengkai 新增包装类型的转换选择
if(mysqlJavaTypeUtil.getMysqlJavaTypeMap().containsKey(mysqlType)){
fieldClass = mysqlJavaTypeUtil.getMysqlJavaTypeMap().get(mysqlType);
}
// field commentMySQL的一般位于field行而pgsql和oralce多位于后面
String fieldComment = null;
if (tableSql.contains("comment on column") && (tableSql.contains("." + columnName + " is ") || tableSql.contains(".`" + columnName + "` is"))) {
//新增对pgsql/oracle的字段备注支持
//COMMENT ON COLUMN public.check_info.check_name IS '检查者名称';
//2018-11-22 lshz0088 正则表达式的点号前面应该加上两个反斜杠否则会认为是任意字符
//2019-4-29 zhengkai 优化对oracle注释comment on column的支持@liukex
tableSql = tableSql.replaceAll(".`" + columnName + "` is", "." + columnName + " is");
Matcher columnCommentMatcher = Pattern.compile("\\." + columnName + " is `").matcher(tableSql);
fieldComment = columnName;
while (columnCommentMatcher.find()) {
String columnCommentTmp = columnCommentMatcher.group();
//System.out.println(columnCommentTmp);
fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim().get();
fieldComment = fieldComment.substring(0, fieldComment.indexOf("`")).trim();
}
} else if (columnLine.contains(" comment")) {
//20200518 zhengkai 修复包含comment关键字的问题
String commentTmp = columnLine.substring(columnLine.lastIndexOf("comment") + 7).trim().get();
// '用户ID',
if (commentTmp.contains("`") || commentTmp.indexOf("`") != commentTmp.lastIndexOf("`")) {
commentTmp = commentTmp.substring(commentTmp.indexOf("`") + 1, commentTmp.lastIndexOf("`"));
}
//解决最后一句是评论无主键且连着)的问题:album_id int(3) default '1' null comment '相册id0 代表头像 1代表照片墙')
if (commentTmp.contains(")")) {
commentTmp = commentTmp.substring(0, commentTmp.lastIndexOf(")") + 1);
}
fieldComment = commentTmp;
} else {
//修复comment不存在导致报错的问题
fieldComment = columnName;
}
FieldInfo fieldInfo = new FieldInfo();
//
fieldInfo.setColumnName(columnName);
fieldInfo.setFieldName(fieldName);
fieldInfo.setFieldClass(fieldClass);
fieldInfo.setSwaggerClass(swaggerClass);
fieldInfo.setFieldComment(fieldComment);
fieldList.add(fieldInfo);
}
}
}
if (fieldList.size() < 1) {
throw new CodeGenerateException("表结构分析失败请检查语句或者提交issue给我");
}
ClassInfo codeJavaInfo = new ClassInfo();
codeJavaInfo.setTableName(tableName);
codeJavaInfo.setClassName(className);
codeJavaInfo.setClassComment(classComment);
codeJavaInfo.setFieldList(fieldList);
codeJavaInfo.setOriginTableName(originTableName);
return codeJavaInfo;
}
private static boolean isNotSpecialColumnLine(NonCaseString columnLine, int lineSeq) {
return (
!columnLine.containsAny(
"key ",
"constraint",
" using ",
"unique ",
"fulltext ",
"index ",
"pctincrease",
"buffer_pool",
"tablespace"
)
&& !(columnLine.contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
&& !(columnLine.contains("primary ") && lineSeq > 3)
);
}
/**
* 解析JSON生成类信息
*
* @param paramInfo
* @return
*/
public static ClassInfo processJsonToClassInfo(ParamInfo paramInfo) {
ClassInfo codeJavaInfo = new ClassInfo();
codeJavaInfo.setTableName("JsonDto");
codeJavaInfo.setClassName("JsonDto");
codeJavaInfo.setClassComment("JsonDto");
//support children json if forget to add '{' in front of json
if (paramInfo.getTableSql().trim().startsWith("\"")) {
paramInfo.setTableSql("{" + paramInfo.getTableSql());
}
if (JSON.isValid(paramInfo.getTableSql())) {
if (paramInfo.getTableSql().trim().startsWith("{")) {
JSONObject jsonObject = JSONObject.parseObject(paramInfo.getTableSql().trim());
//parse FieldList by JSONObject
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonObject));
} else if (paramInfo.getTableSql().trim().startsWith("[")) {
JSONArray jsonArray = JSONArray.parseArray(paramInfo.getTableSql().trim());
//parse FieldList by JSONObject
codeJavaInfo.setFieldList(processJsonObjectToFieldList(jsonArray.getJSONObject(0)));
}
}
return codeJavaInfo;
}
/**
* parse SQL by regex
*
* @param paramInfo
* @return
* @author https://github.com/ydq
*/
public static ClassInfo processTableToClassInfoByRegex(ParamInfo paramInfo) {
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
//return classInfo
ClassInfo codeJavaInfo = new ClassInfo();
//匹配整个ddl将ddl分为表名列sql部分表注释
String DDL_PATTEN_STR = "\\s*create\\s+table\\s+(?<tableName>\\S+)[^\\(]*\\((?<columnsSQL>[\\s\\S]+)\\)[^\\)]+?(comment\\s*(=|on\\s+table)\\s*'(?<tableComment>.*?)'\\s*;?)?$";
Pattern DDL_PATTERN = Pattern.compile(DDL_PATTEN_STR, Pattern.CASE_INSENSITIVE);
//匹配列sql部分分别解析每一列的列名 类型 和列注释
String COL_PATTERN_STR = "\\s*(?<fieldName>\\S+)\\s+(?<fieldType>\\w+)\\s*(?:\\([\\s\\d,]+\\))?((?!comment).)*(comment\\s*'(?<fieldComment>.*?)')?\\s*(,|$)";
Pattern COL_PATTERN = Pattern.compile(COL_PATTERN_STR, Pattern.CASE_INSENSITIVE);
Matcher matcher = DDL_PATTERN.matcher(paramInfo.getTableSql().trim());
if (matcher.find()) {
String tableName = matcher.group("tableName");
String tableComment = matcher.group("tableComment");
codeJavaInfo.setTableName(tableName.replaceAll("'", ""));
codeJavaInfo.setClassName(tableName.replaceAll("'", ""));
codeJavaInfo.setClassComment(tableComment.replaceAll("'", ""));
String columnsSQL = matcher.group("columnsSQL");
if (columnsSQL != null && columnsSQL.length() > 0) {
Matcher colMatcher = COL_PATTERN.matcher(columnsSQL);
while (colMatcher.find()) {
String fieldName = colMatcher.group("fieldName");
String fieldType = colMatcher.group("fieldType");
String fieldComment = colMatcher.group("fieldComment");
if (!"key".equalsIgnoreCase(fieldType)) {
FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldName(fieldName.replaceAll("'", ""));
fieldInfo.setColumnName(fieldName.replaceAll("'", ""));
fieldInfo.setFieldClass(fieldType.replaceAll("'", ""));
fieldInfo.setFieldComment(fieldComment.replaceAll("'", ""));
fieldList.add(fieldInfo);
}
}
}
codeJavaInfo.setFieldList(fieldList);
}
return codeJavaInfo;
}
public static List<FieldInfo> processJsonObjectToFieldList(JSONObject jsonObject) {
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
jsonObject.keySet().stream().forEach(jsonField -> {
FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldName(jsonField);
fieldInfo.setColumnName(jsonField);
fieldInfo.setFieldClass(String.class.getSimpleName());
fieldInfo.setFieldComment("father:" + jsonField);
fieldList.add(fieldInfo);
if (jsonObject.get(jsonField) instanceof JSONArray) {
jsonObject.getJSONArray(jsonField).stream().forEach(arrayObject -> {
FieldInfo fieldInfo2 = new FieldInfo();
fieldInfo2.setFieldName(arrayObject.toString());
fieldInfo2.setColumnName(arrayObject.toString());
fieldInfo2.setFieldClass(String.class.getSimpleName());
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
fieldList.add(fieldInfo2);
});
} else if (jsonObject.get(jsonField) instanceof JSONObject) {
jsonObject.getJSONObject(jsonField).keySet().stream().forEach(arrayObject -> {
FieldInfo fieldInfo2 = new FieldInfo();
fieldInfo2.setFieldName(arrayObject.toString());
fieldInfo2.setColumnName(arrayObject.toString());
fieldInfo2.setFieldClass(String.class.getSimpleName());
fieldInfo2.setFieldComment("children:" + arrayObject.toString());
fieldList.add(fieldInfo2);
});
}
});
if (fieldList.size() < 1) {
throw new CodeGenerateException("JSON解析失败");
}
return fieldList;
}
public static ClassInfo processInsertSqlToClassInfo(ParamInfo paramInfo) {
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
//return classInfo
ClassInfo codeJavaInfo = new ClassInfo();
//get origin sql
String fieldSqlStr = paramInfo.getTableSql().toLowerCase().trim();
fieldSqlStr = fieldSqlStr.replaceAll(" ", " ").replaceAll("\\\\n`", "")
.replaceAll("\\+", "").replaceAll("``", "`").replaceAll("\\\\", "");
String valueStr = fieldSqlStr.substring(fieldSqlStr.lastIndexOf("values") + 6).replaceAll(" ", "").replaceAll("\\(", "").replaceAll("\\)", "");
//get the string between insert into and values
fieldSqlStr = fieldSqlStr.substring(0, fieldSqlStr.lastIndexOf("values"));
System.out.println(fieldSqlStr);
String insertSqlPattenStr = "insert into (?<tableName>.*) \\((?<columnsSQL>.*)\\)";
//String DDL_PATTEN_STR="\\s*create\\s+table\\s+(?<tableName>\\S+)[^\\(]*\\((?<columnsSQL>[\\s\\S]+)\\)[^\\)]+?(comment\\s*(=|on\\s+table)\\s*'(?<tableComment>.*?)'\\s*;?)?$";
Matcher matcher1 = Pattern.compile(insertSqlPattenStr).matcher(fieldSqlStr);
while (matcher1.find()) {
String tableName = matcher1.group("tableName");
//System.out.println("tableName:"+tableName);
codeJavaInfo.setClassName(tableName);
codeJavaInfo.setTableName(tableName);
String columnsSQL = matcher1.group("columnsSQL");
//System.out.println("columnsSQL:"+columnsSQL);
List<String> valueList = new ArrayList<>();
//add values as comment
Arrays.stream(valueStr.split(",")).forEach(column -> {
valueList.add(column);
});
AtomicInteger n = new AtomicInteger(0);
//add column to fleldList
Arrays.stream(columnsSQL.replaceAll(" ", "").split(",")).forEach(column -> {
FieldInfo fieldInfo2 = new FieldInfo();
fieldInfo2.setFieldName(column);
fieldInfo2.setColumnName(column);
fieldInfo2.setFieldClass(String.class.getSimpleName());
if (n.get() < valueList.size()) {
fieldInfo2.setFieldComment(column + " , eg." + valueList.get(n.get()));
}
fieldList.add(fieldInfo2);
n.getAndIncrement();
});
}
if (fieldList.size() < 1) {
throw new CodeGenerateException("INSERT SQL解析失败");
}
codeJavaInfo.setFieldList(fieldList);
return codeJavaInfo;
}
} }

View File

@ -1,5 +1,7 @@
server: server:
port: 1234 port: 1234
http2:
enabled: true
servlet: servlet:
context-path: /generator context-path: /generator
#tomcat: #tomcat:
@ -8,7 +10,7 @@ server:
# max-threads: 10 # max-threads: 10
# background-processor-delay: 30 # background-processor-delay: 30
# basedir: ${user.home}/tomcat/ # basedir: ${user.home}/tomcat/
undertow: undertow:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
# 不要设置过大,如果过大,启动项目会报错:打开文件数过多 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多
io-threads: 4 io-threads: 4
@ -23,7 +25,7 @@ server:
spring: spring:
banner: banner:
charset: UTF-8 charset: UTF-8
http: web:
encoding: encoding:
force: true force: true
charset: UTF-8 charset: UTF-8
@ -47,12 +49,12 @@ spring:
#mvc: #mvc:
# static-path-pattern: /statics/** # static-path-pattern: /statics/**
OEM: OEM:
version: 2024.4 version: 2024.12
header: SQL转Java JPA、MYBATIS实现类代码生成平台 header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现 keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA在线代码生成 title: JAVA在线代码生成
slogan: For reducing the repetitive CRUD work slogan: Release your hands from tedious and repetitive CRUD tasks.
description: <p>SpringBootCodeGenerator(JAVA代码生成平台)<br>又名`大狼狗代码生成器`、`SQL转JAVA`、`SQL转JPA`、`SQL转Mybatis`、`Mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`。</p><p>——以解放双手为目的减少大量的重复CRUD工作可通过建表SQL语句生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper等相关模板代码。</p> description: <p>SpringBootCodeGenerator(JAVA代码生成平台)<br>又名`大狼狗代码生成器`、`SQL转JAVA`、`SQL转JPA`、`SQL转Mybatis`、`Mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`。</p><p>——从繁琐重复的`CRUD工作`中释放你的双手可通过DDL SQL语句或Select SQL语句或简单Json->生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper等相关模板代码。</p>
author: BEJSON author: BEJSON
packageName: www.bejson.com packageName: www.bejson.com
copyright: Powered by Moshow郑锴 , Might the holy light be with you ! copyright: Powered by Moshow郑锴 , Might the holy light be with you !

View File

@ -47,12 +47,12 @@ spring:
#mvc: #mvc:
# static-path-pattern: /statics/** # static-path-pattern: /statics/**
OEM: OEM:
version: 2024.4 version: 2024.12
header: SQL转Java JPA、MYBATIS实现类代码生成平台 header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现 keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA代码生成平台 title: JAVA代码生成平台
slogan: For reducing the repetitive CRUD work slogan: Release your hands from tedious and repetitive CRUD tasks.
description: <p>SpringBootCodeGenerator(JAVA代码生成平台)<br>又名`大狼狗代码生成器`、`SQL转JAVA`、`SQL转JPA`、`SQL转Mybatis`、`Mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`。</p><p>——以解放双手为目的减少大量的重复CRUD工作可通过建表SQL语句生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper等相关模板代码。</p> description: <p>SpringBootCodeGenerator(JAVA代码生成平台)<br>又名`大狼狗代码生成器`、`SQL转JAVA`、`SQL转JPA`、`SQL转Mybatis`、`Mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`。</p><p>——从繁琐重复的`CRUD工作`中释放你的双手可通过DDL SQL语句或Select SQL语句或简单Json->生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper等相关模板代码。</p>
author: Zhengkai.blog.csdn.net author: Zhengkai.blog.csdn.net
packageName: com.software.system packageName: com.software.system
copyright: Powered by Moshow郑锴 , Might the holy light be with you ! copyright: Powered by Moshow郑锴 , Might the holy light be with you !

View File

@ -123,7 +123,7 @@ const vm = new Vue({
vm.formData.tableSql=$.inputArea.getValue(); vm.formData.tableSql=$.inputArea.getValue();
axios.post(basePath+"/code/generate",vm.formData).then(function(res){ axios.post(basePath+"/code/generate",vm.formData).then(function(res){
if(res.code===500){ if(res.code===500){
error("生成失败"); error("生成失败请检查SQL语句!!!");
return; return;
} }
setAllCookie(); setAllCookie();

View File

@ -1 +0,0 @@
{"version": "20231022"}

View File

@ -3,43 +3,43 @@
<!--#################--> <!--#################-->
<!--jquery | vue | element-ui | axios--> <!--jquery | vue | element-ui | axios-->
<script src="//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="//cdn.staticfile.net/jquery/3.5.1/jquery.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> <script src="//cdn.staticfile.net/vue/2.6.12/vue.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.min.js"></script> <script src="//cdn.staticfile.net/element-ui/2.15.14/index.min.js"></script>
<link rel="stylesheet" href="//cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/theme-chalk/index.min.css"> <link rel="stylesheet" href="//cdn.staticfile.net/element-ui/2.15.0/theme-chalk/index.min.css">
<script src="//cdn.bootcdn.net/ajax/libs/axios/0.1.0/axios.min.js"></script> <script src="//cdn.staticfile.net/axios/0.1.0/axios.min.js"></script>
<!--common.js--> <!--common.js-->
<script src="${request.contextPath}/statics/js/common.js"></script> <script src="${request.contextPath}/statics/js/common.js"></script>
<!-- <link rel="stylesheet" href="${request.contextPath}/statics/css/main.css"> --> <!-- <link rel="stylesheet" href="${request.contextPath}/statics/css/main.css"> -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="//cdn.bootcdn.net/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="//cdn.staticfile.net/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/respond.js/1.4.2/respond.min.js"></script> <script src="//cdn.staticfile.net/respond.js/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
<!-- Bootstrap 4 --> <!-- Bootstrap 4 -->
<script src="//cdn.bootcdn.net/ajax/libs/bootstrap/4.6.2/js/bootstrap.bundle.min.js"></script> <script src="//cdn.staticfile.net/bootstrap/4.6.2/js/bootstrap.bundle.min.js"></script>
<!-- AdminLTE 3 --> <!-- AdminLTE 3 -->
<script src="//cdn.bootcdn.net/ajax/libs/admin-lte/3.2.0/js/adminlte.min.js"></script> <script src="//cdn.staticfile.net/admin-lte/3.2.0/js/adminlte.min.js"></script>
<!-- Toastr 2 --> <!-- Toastr 2 -->
<script src="//cdn.bootcdn.net/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script> <script src="//cdn.staticfile.net/toastr.js/2.1.4/toastr.min.js"></script>
<!-- import codemirror --> <!-- import codemirror -->
<script src="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/codemirror.min.js"></script> <script src="//cdn.staticfile.net/codemirror/6.65.7/codemirror.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/mode/sql/sql.min.js"></script> <script src="//cdn.staticfile.net/codemirror/6.65.7/mode/sql/sql.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/mode/xml/xml.min.js"></script> <script src="//cdn.staticfile.net/codemirror/6.65.7/mode/xml/xml.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/mode/clike/clike.min.js"></script> <script src="//cdn.staticfile.net/codemirror/6.65.7/mode/clike/clike.min.js"></script>
<script src="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/mode/javascript/javascript.min.js"></script> <script src="//cdn.staticfile.net/codemirror/6.65.7/mode/javascript/javascript.min.js"></script>
<link rel="stylesheet" href="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/codemirror.min.css"> <link rel="stylesheet" href="//cdn.staticfile.net/codemirror/6.65.7/codemirror.min.css">
<link rel="stylesheet" href="//cdn.bootcdn.net/ajax/libs/codemirror/6.65.7/theme/idea.min.css"> <link rel="stylesheet" href="//cdn.staticfile.net/codemirror/6.65.7/theme/idea.min.css">
<!--bootsrap css--> <!--bootsrap css-->
<link rel="stylesheet" href="//cdn.bootcdn.net/ajax/libs/bootstrap/4.6.2/css/bootstrap.min.css"> <link rel="stylesheet" href="//cdn.staticfile.net/bootstrap/4.6.2/css/bootstrap.min.css">
<link rel="stylesheet" href="${request.contextPath}/statics/plugins/fontawesome-free/css/all.min.css"> <link rel="stylesheet" href="${request.contextPath}/statics/plugins/fontawesome-free/css/all.min.css">
<!-- Admin-LTE主题样式 --> <!-- Admin-LTE主题样式 -->
<link rel="stylesheet" href="//cdn.bootcdn.net/ajax/libs/admin-lte/3.2.0/css/adminlte.min.css"> <link rel="stylesheet" href="//cdn.staticfile.net/admin-lte/3.2.0/css/adminlte.min.css">
<!-- Toastr CSS --> <!-- Toastr CSS -->
<link href="//cdn.bootcdn.net/ajax/libs/toastr.js/2.1.4/toastr.min.css" rel="stylesheet"> <link href="//cdn.staticfile.net/toastr.js/2.1.4/toastr.min.css" rel="stylesheet">

View File

@ -6,8 +6,8 @@ by https://zhengkai.blog.csdn.net
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>JAVA代码生成平台</title>
<#include "/header.html"> <#include "/header.html">
<title>${(value.title)!!}</title>
</head> </head>
<body class="hold-transition layout-top-nav"> <body class="hold-transition layout-top-nav">
<div class="wrapper"> <div class="wrapper">
@ -17,7 +17,7 @@ by https://zhengkai.blog.csdn.net
<div class="container"> <div class="container">
<a href="#" class="navbar-brand"> <a href="#" class="navbar-brand">
<img src="${request.contextPath}/statics/img/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8"> <img src="${request.contextPath}/statics/img/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8">
<span class="brand-text font-weight-light">JAVA代码生成平台</span> <span class="brand-text font-weight-light">${(value.title)!!}</span>
</a> </a>
<button class="navbar-toggler order-1" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler order-1" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
@ -25,7 +25,7 @@ by https://zhengkai.blog.csdn.net
</button> </button>
<div class="collapse navbar-collapse order-3" id="navbarCollapse"> <div class="collapse navbar-collapse order-3" id="navbarCollapse">
<i class="fa fa-fw fa-space-shuttle"></i><a>For reducing the repetitive CRUD work</a> <i class="fa fa-fw fa-space-shuttle"></i><a>${(value.slogan)!!}</a>
</div> </div>
<!-- 右侧导航栏链接 --> <!-- 右侧导航栏链接 -->

View File

@ -80,6 +80,7 @@
<el-option label="DDL SQL" value="sql"></el-option> <el-option label="DDL SQL" value="sql"></el-option>
<el-option label="JSON" value="json"></el-option> <el-option label="JSON" value="json"></el-option>
<el-option label="INSERT SQL" value="insert-sql"> <el-option label="INSERT SQL" value="insert-sql">
<el-option label="SELECT SQL by SQL Parser" value="select-sql">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>

View File

@ -1,27 +0,0 @@
import com.softdev.system.generator.util.StringUtils;
public class FooTest {
public static void main(String[] args) {
// String updateTime = StringUtils.underlineToCamelCase("updateTime");
// System.out.println(updateTime);
// System.out.println(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "userName"));
// System.out.println(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "userNAme-UUU"));
System.out.println(StringUtils.toUnderline("userName",false));
System.out.println(StringUtils.toUnderline("UserName",false));
System.out.println(StringUtils.toUnderline("user_NameGgg_x-UUU",false));
System.out.println(StringUtils.toUnderline("username",false));
System.out.println(StringUtils.toUnderline("userName",true));
System.out.println(StringUtils.toUnderline("UserName",true));
System.out.println(StringUtils.toUnderline("user_NameGgg_x-UUU",true));
System.out.println(StringUtils.toUnderline("username",true));
System.out.println(StringUtils.underlineToCamelCase("CREATE_TIME"));
}
}

View File

@ -0,0 +1,104 @@
package com.softdev.system.generator.util;
import org.junit.Test;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertFalse;
public class StringUtilsPlusTest {
@Test
public void toLowerCamel() {
System.out.println(StringUtilsPlus.toLowerCamel("hello_world"));
System.out.println(StringUtilsPlus.toLowerCamel("HELLO_WO-RLD-IK"));
System.out.println(StringUtilsPlus.toLowerCamel("HELLO_WORLD-IKabc"));
System.out.println(StringUtilsPlus.toLowerCamel("HELLO-WORLD-IKabc"));
System.out.println(StringUtilsPlus.toLowerCamel("HELLO-123WORLD-IKabc"));
System.out.println(StringUtilsPlus.toLowerCamel("helloWorldOKla"));
assertEquals("helloWorldChina", StringUtilsPlus.toLowerCamel("hello_-_world-cHina"));
}
@Test
public void upperCaseFirstShouldReturnStringWithFirstLetterCapitalized() {
assertEquals("Hello", StringUtilsPlus.upperCaseFirst("hello"));
}
@Test
public void upperCaseFirstShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtilsPlus.upperCaseFirst(""));
}
@Test
public void lowerCaseFirstShouldReturnStringWithFirstLetterLowercased() {
assertEquals("hello", StringUtilsPlus.lowerCaseFirst("Hello"));
}
@Test
public void lowerCaseFirstShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtilsPlus.lowerCaseFirst(""));
}
@Test
public void underlineToCamelCaseShouldReturnCamelCaseString() {
assertEquals("helloWorld", StringUtilsPlus.underlineToCamelCase("hello_world"));
}
@Test
public void underlineToCamelCaseShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtilsPlus.underlineToCamelCase(""));
}
@Test
public void toUnderlineShouldReturnUnderlinedString() {
assertEquals("hello_world", StringUtilsPlus.toUnderline("helloWorld", false));
}
@Test
public void toUnderlineShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtilsPlus.toUnderline("", false));
}
@Test
public void toCamelShouldReturnCamelCaseString() {
assertEquals("helloWorld", StringUtilsPlus.toLowerCamel("hello_world"));
}
@Test
public void toCamelShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtilsPlus.toLowerCamel(""));
}
@Test
public void isNotNullShouldReturnTrueWhenStringIsNotEmpty() {
assertTrue(StringUtilsPlus.isNotNull("hello"));
}
@Test
public void isNotNullShouldReturnFalseWhenStringIsEmpty() {
assertFalse(StringUtilsPlus.isNotNull(""));
}
public static void main(String[] args) {
// String updateTime = StringUtils.underlineToCamelCase("updateTime");
// System.out.println(updateTime);
// System.out.println(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "userName"));
// System.out.println(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "userNAme-UUU"));
System.out.println(StringUtilsPlus.toUnderline("userName",false));
System.out.println(StringUtilsPlus.toUnderline("UserName",false));
System.out.println(StringUtilsPlus.toUnderline("user_NameGgg_x-UUU",false));
System.out.println(StringUtilsPlus.toUnderline("username",false));
System.out.println(StringUtilsPlus.toUnderline("userName",true));
System.out.println(StringUtilsPlus.toUnderline("UserName",true));
System.out.println(StringUtilsPlus.toUnderline("user_NameGgg_x-UUU",true));
System.out.println(StringUtilsPlus.toUnderline("username",true));
System.out.println(StringUtilsPlus.underlineToCamelCase("CREATE_TIME"));
}
}

View File

@ -1,81 +0,0 @@
package com.softdev.system.generator.util;
import org.junit.Test;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertFalse;
public class StringUtilsTest {
@Test
public void toLowerCamel() {
System.out.println(StringUtils.toLowerCamel("hello_world"));
System.out.println(StringUtils.toLowerCamel("HELLO_WO-RLD-IK"));
System.out.println(StringUtils.toLowerCamel("HELLO_WORLD-IKabc"));
System.out.println(StringUtils.toLowerCamel("HELLO-WORLD-IKabc"));
System.out.println(StringUtils.toLowerCamel("HELLO-123WORLD-IKabc"));
System.out.println(StringUtils.toLowerCamel("helloWorldOKla"));
assertEquals("helloWorldChina", StringUtils.toLowerCamel("hello_-_world-cHina"));
}
@Test
public void upperCaseFirstShouldReturnStringWithFirstLetterCapitalized() {
assertEquals("Hello", StringUtils.upperCaseFirst("hello"));
}
@Test
public void upperCaseFirstShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtils.upperCaseFirst(""));
}
@Test
public void lowerCaseFirstShouldReturnStringWithFirstLetterLowercased() {
assertEquals("hello", StringUtils.lowerCaseFirst("Hello"));
}
@Test
public void lowerCaseFirstShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtils.lowerCaseFirst(""));
}
@Test
public void underlineToCamelCaseShouldReturnCamelCaseString() {
assertEquals("helloWorld", StringUtils.underlineToCamelCase("hello_world"));
}
@Test
public void underlineToCamelCaseShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtils.underlineToCamelCase(""));
}
@Test
public void toUnderlineShouldReturnUnderlinedString() {
assertEquals("hello_world", StringUtils.toUnderline("helloWorld", false));
}
@Test
public void toUnderlineShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtils.toUnderline("", false));
}
@Test
public void toCamelShouldReturnCamelCaseString() {
assertEquals("helloWorld", StringUtils.toLowerCamel("hello_world"));
}
@Test
public void toCamelShouldReturnEmptyStringWhenInputIsEmpty() {
assertEquals("", StringUtils.toLowerCamel(""));
}
@Test
public void isNotNullShouldReturnTrueWhenStringIsNotEmpty() {
assertTrue(StringUtils.isNotNull("hello"));
}
@Test
public void isNotNullShouldReturnFalseWhenStringIsEmpty() {
assertFalse(StringUtils.isNotNull(""));
}
}

21
pom.xml
View File

@ -11,7 +11,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version> <version>3.4.1</version>
</parent> </parent>
<modules> <modules>
@ -28,6 +28,13 @@
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/com.github.jsqlparser/jsqlparser -->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>5.0</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
@ -56,18 +63,18 @@
<dependency> <dependency>
<groupId>com.alibaba.fastjson2</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId> <artifactId>fastjson2</artifactId>
<version>2.0.49</version> <version>2.0.53</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba.fastjson2</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId> <artifactId>fastjson2-extension</artifactId>
<version>2.0.49</version> <version>2.0.53</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension-spring6 --> <!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension-spring6 -->
<dependency> <dependency>
<groupId>com.alibaba.fastjson2</groupId> <groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension-spring6</artifactId> <artifactId>fastjson2-extension-spring6</artifactId>
<version>2.0.49</version> <version>2.0.53</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api --> <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
@ -103,7 +110,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.32</version> <version>1.18.36</version>
</dependency> </dependency>
<!-- freemarker --> <!-- freemarker -->
@ -130,13 +137,13 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.14.0</version> <version>3.17.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.16.1</version> <version>2.18.0</version>
</dependency> </dependency>
</dependencies> </dependencies>