JSqlParser Engine全新升级,目前Select SQL模式相对稳定!

This commit is contained in:
Moshow郑锴 2025-09-14 00:40:39 +08:00
parent 2e74d50296
commit 995e1e608a
8 changed files with 100 additions and 75 deletions

View File

@ -70,13 +70,12 @@
# 更新预告 # 更新预告
1.计划加入AI来帮忙生成更多样式的模板 1.计划加入AI来帮忙生成更多样式的模板
2.计划使用AI来改善现有模板 2.改进JSqlParser Engine (Select SQL and Create SQL)
3.深度支持Select SQL模式以及探索JSON模式更多可能
# Update Logs # Update Logs
| 更新日期 | 更新内容 | | 更新日期 | 更新内容 |
|:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 2025.09.13 | Create SQL by JSqlParser Engine升级<br>更新SpringBoot等类库版本修复漏洞<br>修复CDN问题切换为staticfile.org | | 2025.09.13 | JSqlParser Engine全新升级目前Select SQL模式相对稳定! <br>更新SpringBoot等类库版本修复漏洞<br>修复CDN问题切换为staticfile.org |
| 2025.03.31 | 优化说明 | | 2025.03.31 | 优化说明 |
| 2025.03.16 | NewUI V2前端优化<br>移除不必要内容优化Local和CDN静态文件引入。<br><br>修复由于SQL类型大写导致无法转换的问题。感谢@zzy-design的反馈<br><br>JPA模板优化感谢@PenroseYang的反馈<br>修复不开启Lombok情况下Set/Get方法生成问题;<br>修复importDdate判断为true后没有引入日期类的问题<br> | | 2025.03.16 | NewUI V2前端优化<br>移除不必要内容优化Local和CDN静态文件引入。<br><br>修复由于SQL类型大写导致无法转换的问题。感谢@zzy-design的反馈<br><br>JPA模板优化感谢@PenroseYang的反馈<br>修复不开启Lombok情况下Set/Get方法生成问题;<br>修复importDdate判断为true后没有引入日期类的问题<br> |
| 2024.12.29 | 优化前端加载速度优化输出代码着色CDN改字节跳动静态资源公共库。<br> | | 2024.12.29 | 优化前端加载速度优化输出代码着色CDN改字节跳动静态资源公共库。<br> |

View File

@ -88,7 +88,7 @@ public class GeneratorController {
classInfo = generatorService.generateSelectSqlBySQLPraser(paramInfo); classInfo = generatorService.generateSelectSqlBySQLPraser(paramInfo);
break; break;
case "create-sql": case "create-sql":
//SelectSqlBySQLPraser模式:parse select sql by JSqlParser //CreateSqlBySQLPraser模式:parse create sql by JSqlParser
classInfo = generatorService.generateCreateSqlBySQLPraser(paramInfo); classInfo = generatorService.generateCreateSqlBySQLPraser(paramInfo);
break; break;
default: default:

View File

@ -96,6 +96,7 @@ public class GeneratorServiceImpl implements GeneratorService {
if (!CollectionUtils.isEmpty(tableNameList)) { if (!CollectionUtils.isEmpty(tableNameList)) {
String tableName = tableNameList.get(0).trim(); String tableName = tableNameList.get(0).trim();
classInfo.setTableName(tableName); classInfo.setTableName(tableName);
classInfo.setOriginTableName(tableName);
String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName)); String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName));
if (className.contains("_")) { if (className.contains("_")) {
className = className.replaceAll("_", ""); className = className.replaceAll("_", "");
@ -121,21 +122,15 @@ public class GeneratorServiceImpl implements GeneratorService {
fieldName=fieldName.contains(".")?fieldName.substring(fieldName.indexOf(".")+1):fieldName; fieldName=fieldName.contains(".")?fieldName.substring(fieldName.indexOf(".")+1):fieldName;
//转换前 //转换前
fieldInfo.setColumnName(fieldName); fieldInfo.setColumnName(fieldName);
switch ((String) paramInfo.getOptions().get("nameCaseType")) { fieldName = switch ((String) paramInfo.getOptions().get("nameCaseType")) {
case ParamInfo.NAME_CASE_TYPE.CAMEL_CASE: case ParamInfo.NAME_CASE_TYPE.CAMEL_CASE ->
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰 // 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰
fieldName = StringUtilsPlus.toLowerCamel(aliasName); StringUtilsPlus.toLowerCamel(aliasName);
break; case ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE -> StringUtilsPlus.toUnderline(aliasName, false);
case ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE: case ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE ->
fieldName = StringUtilsPlus.toUnderline(aliasName, false); StringUtilsPlus.toUnderline(aliasName.toUpperCase(), true);
break; default -> aliasName;
case ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE: };
fieldName = StringUtilsPlus.toUnderline(aliasName.toUpperCase(), true);
break;
default:
fieldName = aliasName;
break;
}
//转换后 //转换后
fieldInfo.setFieldName(fieldName); fieldInfo.setFieldName(fieldName);
@ -157,62 +152,57 @@ public class GeneratorServiceImpl implements GeneratorService {
@Override @Override
public ClassInfo generateCreateSqlBySQLPraser(ParamInfo paramInfo) throws Exception { public ClassInfo generateCreateSqlBySQLPraser(ParamInfo paramInfo) throws Exception {
ClassInfo classInfo = new ClassInfo(); ClassInfo classInfo = new ClassInfo();
Statement statement = CCJSqlParserUtil.parse(paramInfo.getTableSql()); Statement statement = null;
CCJSqlParserManager parserManager = new CCJSqlParserManager(); try {
statement = parserManager.parse(new StringReader(paramInfo.getTableSql())); statement = CCJSqlParserUtil.parse(paramInfo.getTableSql().trim());
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); // 创建表名发现者对象 }catch (Exception e) {
List<String> tableNameList = tablesNamesFinder.getTableList(statement); // 获取到表名列表 e.printStackTrace();
//一般这里应该只解析到一个表名除非多个表名取第一个 throw new SqlException("SQL语法错误:"+e.getMessage());
if (!CollectionUtils.isEmpty(tableNameList)) {
String tableName = tableNameList.get(0).trim();
classInfo.setTableName(tableName);
String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName));
if (className.contains("_")) {
className = className.replaceAll("_", "");
}
classInfo.setClassName(className);
classInfo.setClassComment(paramInfo.getTableSql());
} }
//解析查询元素
Select select = null;
select = (Select) CCJSqlParserUtil.parse(paramInfo.getTableSql());
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
// field List // 确保是CREATE TABLE语句
if (!(statement instanceof CreateTable createTable)) {
throw new SqlException("检测到SQL语句不是DLL CREATE TABLE语句");
}
// 提取表名
String tableName = createTable.getTable().getName();
classInfo.setTableName(tableName);
String className = StringUtilsPlus.upperCaseFirst(StringUtilsPlus.underlineToCamelCase(tableName));
if (className.contains("_")) {
className = className.replaceAll("_", "");
}
classInfo.setClassName(className);
classInfo.setOriginTableName(tableName);
classInfo.setClassComment(paramInfo.getTableSql());
// 提取字段信息
List<FieldInfo> fieldList = new ArrayList<FieldInfo>(); List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
selectItems.forEach(t->{ List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();
FieldInfo fieldInfo = new FieldInfo();
String fieldName = ((Column)t.getExpression()).getColumnName(); if (columnDefinitions != null) {
String aliasName = t.getAlias() != null ? t.getAlias().getName() : ((Column)t.getExpression()).getColumnName(); for (ColumnDefinition columnDefinition : columnDefinitions) {
//存储原始字段名 FieldInfo fieldInfo = new FieldInfo();
fieldInfo.setFieldComment(aliasName);fieldInfo.setColumnName(aliasName); String columnName = columnDefinition.getColumnName();
//处理字段名是t.xxx的情况 fieldInfo.setColumnName(columnName);
fieldName=fieldName.contains(".")?fieldName.substring(fieldName.indexOf(".")+1):fieldName; fieldInfo.setFieldComment(columnDefinition.toString());
//转换前
fieldInfo.setColumnName(fieldName); // 根据命名规则转换字段名
switch ((String) paramInfo.getOptions().get("nameCaseType")) { String fieldName = switch ((String) paramInfo.getOptions().get("nameCaseType")) {
case ParamInfo.NAME_CASE_TYPE.CAMEL_CASE: case ParamInfo.NAME_CASE_TYPE.CAMEL_CASE -> StringUtilsPlus.toLowerCamel(columnName);
// 2024-1-27 L&J 适配任意(maybe)原始风格转小写驼峰 case ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE -> StringUtilsPlus.toUnderline(columnName, false);
fieldName = StringUtilsPlus.toLowerCamel(aliasName); case ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE ->
break; StringUtilsPlus.toUnderline(columnName.toUpperCase(), true);
case ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE: default -> columnName;
fieldName = StringUtilsPlus.toUnderline(aliasName, false); };
break; fieldInfo.setFieldName(fieldName);
case ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE:
fieldName = StringUtilsPlus.toUnderline(aliasName.toUpperCase(), true); // 设置字段类型为String因为无法准确推测类型
break; fieldInfo.setFieldClass("String");
default: fieldList.add(fieldInfo);
fieldName = aliasName;
break;
} }
//转换后 }
fieldInfo.setFieldName(fieldName);
//无法推测类型所有都set为String
fieldInfo.setFieldClass("String");
fieldList.add(fieldInfo);
});
classInfo.setFieldList(fieldList); classInfo.setFieldList(fieldList);
log.info("classInfo:{}", JSON.toJSONString(classInfo)); log.info("classInfo:{}", JSON.toJSONString(classInfo));
return classInfo; return classInfo;

View File

@ -0,0 +1,35 @@
package com.softdev.system.generator.util;
import java.io.Serial;
/**
* @author xuxueli 2018-05-02 21:10:28
*/
public class SqlException extends RuntimeException {
@Serial
private static final long serialVersionUID = 42L;
public SqlException() {
super();
}
public SqlException(String msg) {
super(msg);
}
public SqlException(String msg, Throwable cause) {
super(msg, cause);
}
public SqlException(Throwable cause) {
super(cause);
}
public SqlException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -59,4 +59,4 @@ OEM:
returnUtilSuccess: ResponseUtil.success returnUtilSuccess: ResponseUtil.success
returnUtilFailure: ResponseUtil.error returnUtilFailure: ResponseUtil.error
outputStr: http://zhengkai.blog.csdn.net outputStr: http://zhengkai.blog.csdn.net
mode: CDN mode: local

View File

@ -1,3 +1,3 @@
spring: spring:
profiles: profiles:
active: bejson active: dev

View File

@ -123,8 +123,9 @@ const vm = new Vue({
//get value from codemirror //get value from codemirror
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.status===500||res.data.code===500){
error("生成失败请检查SQL语句!!!"); console.log(res);
error("生成失败请检查SQL语句!!!"+res.data.msg);
return; return;
} }
setAllCookie(); setAllCookie();

View File

@ -100,7 +100,7 @@
</div> </div>
<div class="card-body"> <div class="card-body">
<el-form-item label="生成引擎"> <el-form-item label="🌟🌟🌟引擎">
<el-select v-model="formData.options.dataType"> <el-select v-model="formData.options.dataType">
<el-option label="DDL SQL@自研SQL解析引擎" value="sql"></el-option> <el-option label="DDL SQL@自研SQL解析引擎" value="sql"></el-option>
<el-option label="SELECT SQL@JSqlParser引擎" value="select-sql"></el-option> <el-option label="SELECT SQL@JSqlParser引擎" value="select-sql"></el-option>