diff --git a/generator-web/src/main/java/com/softdev/system/generator/entity/NonCaseString.java b/generator-web/src/main/java/com/softdev/system/generator/entity/NonCaseString.java
new file mode 100644
index 00000000..4472156b
--- /dev/null
+++ b/generator-web/src/main/java/com/softdev/system/generator/entity/NonCaseString.java
@@ -0,0 +1,152 @@
+package com.softdev.system.generator.entity;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * String 包装类
+ *
+ * 忽略大小写
+ **考虑增加这个类是, 如果在 StringUtils 中加工具方法, 使用起来代码非常冗长且不方便
+ * @author Nisus
+ * @see String
+ */
+@AllArgsConstructor
+public class NonCaseString implements CharSequence {
+ private String value;
+
+ public static NonCaseString of(String str) {
+ assert str != null;
+ return new NonCaseString(str);
+ }
+
+
+ /**
+ * {@link String#indexOf(String)} 增强, 忽略大小写
+ */
+ public int indexOf(String m) {
+ String text = this.value;
+ if (text == null || m == null || text.length() < m.length()) {
+ return -1;
+ }
+ return text.toLowerCase().indexOf(m.toLowerCase());
+ }
+
+ /**
+ * {@link String#lastIndexOf(String)} 增强, 忽略大小写
+ */
+ public int lastIndexOf(String m) {
+ String text = this.value;
+ if (text == null || m == null || text.length() < m.length()) {
+ return -1;
+ }
+ return text.toLowerCase().lastIndexOf(m.toLowerCase());
+ }
+
+ /**
+ * 是否包含, 大小写不敏感
+ *
true
+ * "abcxyz" 包含 "ABC" => true
+ * "abcxyz" 包含 "aBC" => true
+ *
+ *
+ * @param m 被包含字符串
+ */
+ public boolean contains(String m) {
+ String text = this.value;
+ if (text.length() < m.length()) {
+ return false;
+ }
+ return text.toLowerCase().contains(m.toLowerCase());
+ }
+
+ /**
+ * 任意一个包含返回true
+ *
+ * containsAny("abcdef", "a", "b)
+ * 等价
+ * "abcdef".contains("a") || "abcdef".contains("b")
+ *
+ *
+ * @param matchers 多个要判断的被包含项
+ */
+ public boolean containsAny(String... matchers) {
+ for (String matcher : matchers) {
+ if (contains(matcher)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 所有都包含才返回true
+ *
+ * @param matchers 多个要判断的被包含项
+ */
+ public boolean containsAllIgnoreCase(String... matchers) {
+ for (String matcher : matchers) {
+ if (contains(matcher) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public NonCaseString trim() {
+ return NonCaseString.of(this.value.trim());
+ }
+
+ public NonCaseString replace(char oldChar, char newChar) {
+ return NonCaseString.of(this.value.replace(oldChar, newChar));
+ }
+
+ public NonCaseString replaceAll(String regex, String replacement) {
+ return NonCaseString.of(this.value.replaceAll(regex, replacement));
+ }
+
+ public NonCaseString substring(int beginIndex) {
+ return NonCaseString.of(this.value.substring(beginIndex));
+ }
+
+ public NonCaseString substring(int beginIndex, int endIndex) {
+ return NonCaseString.of(this.value.substring(beginIndex, endIndex));
+ }
+
+ public boolean isNotEmpty() {
+ return !this.value.isEmpty();
+ }
+
+ @Override
+ public int length() {
+ return this.value.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return this.value.charAt(index);
+ }
+
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return this.value.subSequence(start, end);
+ }
+
+ public String[] split(String regex) {
+ return this.value.split(regex);
+ }
+
+
+ /**
+ * @return 原始字符串
+ */
+ public String get() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return this.value;
+ }
+}
diff --git a/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java b/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
index f123ed01..061d94ae 100644
--- a/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
+++ b/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
@@ -40,7 +40,7 @@ public static String underlineToCamelCase(String underscoreName) {
boolean flag = false;
for (int i = 0; i < underscoreName.length(); i++) {
char ch = underscoreName.charAt(i);
- if ("_".charAt(0) == ch) {
+ if ('_' == ch) {
flag = true;
} else {
if (flag) {
@@ -54,6 +54,42 @@ public static String underlineToCamelCase(String underscoreName) {
}
return result.toString();
}
+
+ /**
+ * 转 user_name 风格
+ *
+ * 不管原始是什么风格
+ */
+ public static String toUnderline(String str, boolean upperCase) {
+ if (str == null || str.trim().isEmpty()) {
+ return str;
+ }
+
+ StringBuilder result = new StringBuilder();
+ boolean preIsUnderscore = false;
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ if (ch == '_') {
+ preIsUnderscore = true;
+ } else if (ch == '-') {
+ ch = '_';
+ preIsUnderscore = true; // -A -> _a
+ } else if (ch >= 'A' && ch <= 'Z') {
+ // A -> _a
+ if (!preIsUnderscore && i > 0) { // _A -> _a
+ result.append("_");
+ }
+ preIsUnderscore = false;
+ } else {
+ preIsUnderscore = false;
+ }
+ result.append(upperCase ? Character.toUpperCase(ch) : Character.toLowerCase(ch));
+ }
+
+ return result.toString();
+ }
+
+
public static boolean isNotNull(String str){
return org.apache.commons.lang3.StringUtils.isNotEmpty(str);
}
diff --git a/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java b/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java
index 979a8a04..7104ad83 100644
--- a/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java
+++ b/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java
@@ -1,18 +1,16 @@
package com.softdev.system.generator.util;
-import com.softdev.system.generator.util.mysqlJavaTypeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.FieldInfo;
+import com.softdev.system.generator.entity.NonCaseString;
import com.softdev.system.generator.entity.ParamInfo;
import java.io.IOException;
-import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
@@ -34,7 +32,7 @@ public class TableParseUtil {
public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
throws IOException {
//process the param
- String tableSql = paramInfo.getTableSql();
+ NonCaseString tableSql = NonCaseString.of(paramInfo.getTableSql());
String nameCaseType = MapUtil.getString(paramInfo.getOptions(),"nameCaseType");
Boolean isPackageType = MapUtil.getBoolean(paramInfo.getOptions(),"isPackageType");
@@ -42,15 +40,20 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
throw new CodeGenerateException("Table structure can not be empty. 表结构不能为空。");
}
//deal with special character
- tableSql = tableSql.trim().replaceAll("'", "`").replaceAll("\"", "`").replaceAll(",", ",").toLowerCase();
+ 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;
- if (tableSql.contains("TABLE") && tableSql.contains("(")) {
- tableName = tableSql.substring(tableSql.indexOf("TABLE") + 5, tableSql.indexOf("("));
- } else if (tableSql.contains("table") && tableSql.contains("(")) {
- tableName = tableSql.substring(tableSql.indexOf("table") + 5, tableSql.indexOf("("));
+ 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.表结构不正确。");
}
@@ -88,9 +91,11 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
String classComment = null;
//mysql是comment=,pgsql/oracle是comment on table,
//2020-05-25 优化表备注的获取逻辑
- if (tableSql.contains("comment=") || tableSql.contains("comment on table")) {
- String classCommentTmp = (tableSql.contains("comment=")) ?
- tableSql.substring(tableSql.lastIndexOf("comment=") + 8).trim() : tableSql.substring(tableSql.lastIndexOf("comment on table") + 17).trim();
+ 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("`"));
@@ -109,7 +114,7 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
List fieldList = new ArrayList();
// 正常( ) 内的一定是字段相关的定义。
- String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")"));
+ String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")")).get();
// 匹配 comment,替换备注里的小逗号, 防止不小心被当成切割符号切割
String commentPattenStr1 = "comment `(.*?)\\`";
@@ -149,7 +154,8 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
if (fieldLineList.length > 0) {
int i = 0;
//i为了解决primary key关键字出现的地方,出现在前3行,一般和id有关
- for (String columnLine : fieldLineList) {
+ 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',
@@ -158,13 +164,10 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
// 2019-2-22 zhengkai 要在条件中使用复杂的表达式
// 2019-4-29 zhengkai 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 )
// 2020-10-20 zhengkai 优化对fulltext/index关键字的处理(感谢@WEGFan的反馈)
- boolean specialFlag = (!columnLine.contains("key ") && !columnLine.contains("constraint") && !columnLine.contains("using") && !columnLine.contains("unique ")
- && !(columnLine.contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
- && !columnLine.contains("fulltext ") && !columnLine.contains("index ")
- && !columnLine.contains("pctincrease")
- && !columnLine.contains("buffer_pool") && !columnLine.contains("tablespace")
- && !(columnLine.contains("primary ") && i > 3));
- if (specialFlag) {
+ // 2023-8-27 zhangfei 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
+ boolean notSpecialFlag = isNotSpecialColumnLine(columnLine, i);
+
+ if (notSpecialFlag) {
//如果是oracle的number(x,x),可能出现最后分割残留的,x),这里做排除处理
if (columnLine.length() < 5) {
continue;
@@ -174,7 +177,7 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
columnLine = columnLine.replaceAll("`", " ").replaceAll("\"", " ").replaceAll("'", "").replaceAll(" ", " ").trim();
//如果遇到username varchar(65) default '' not null,这种情况,判断第一个空格是否比第一个引号前
try {
- columnName = columnLine.substring(0, columnLine.indexOf(" "));
+ columnName = columnLine.substring(0, columnLine.indexOf(" ")).get();
} catch (StringIndexOutOfBoundsException e) {
System.out.println("err happened: " + columnLine);
throw e;
@@ -182,6 +185,7 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
// field Name
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
+ // 2023-8-27 zhangfei 支持原始列名任意命名风格, 不依赖用户是否输入下划线
String fieldName = null;
if (ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)) {
fieldName = StringUtils.lowerCaseFirst(StringUtils.underlineToCamelCase(columnName));
@@ -189,9 +193,9 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
fieldName = fieldName.replaceAll("_", "");
}
} else if (ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE.equals(nameCaseType)) {
- fieldName = StringUtils.lowerCaseFirst(columnName);
+ fieldName = StringUtils.toUnderline(columnName, false);
} else if (ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)) {
- fieldName = StringUtils.lowerCaseFirst(columnName.toUpperCase());
+ fieldName = StringUtils.toUnderline(columnName.toUpperCase(), true);
} else {
fieldName = columnName;
}
@@ -228,12 +232,12 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
while (columnCommentMatcher.find()) {
String columnCommentTmp = columnCommentMatcher.group();
//System.out.println(columnCommentTmp);
- fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim();
+ 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();
+ 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("`"));
@@ -275,6 +279,24 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
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生成类信息
*
diff --git a/generator-web/src/main/resources/statics/js/main.js b/generator-web/src/main/resources/statics/js/main.js
index fd01eb03..369de1c6 100644
--- a/generator-web/src/main/resources/statics/js/main.js
+++ b/generator-web/src/main/resources/statics/js/main.js
@@ -36,6 +36,9 @@ const vm = new Vue({
" 'user_name' varchar(255) NOT NULL COMMENT '用户名',\n" +
" 'status' tinyint(1) NOT NULL COMMENT '状态',\n" +
" 'create_time' datetime NOT NULL COMMENT '创建时间',\n" +
+ //下面可以留着方便开发调试时打开
+ // " `updateTime` datetime NOT NULL COMMENT '更新时间',\n" +
+ // " ABc_under_Line-Hypen-CamelCase varchar comment '乱七八糟的命名风格',\n" +
" PRIMARY KEY ('user_id')\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息'",
options: {
diff --git a/generator-web/src/test/java/FooTest.java b/generator-web/src/test/java/FooTest.java
new file mode 100644
index 00000000..1a9254fe
--- /dev/null
+++ b/generator-web/src/test/java/FooTest.java
@@ -0,0 +1,25 @@
+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));
+ }
+
+
+}
From b447d9842335881bc7dbf50cad5edf1bcd8ec445 Mon Sep 17 00:00:00 2001
From: moshow
Date: Sun, 22 Oct 2023 14:46:42 +0800
Subject: [PATCH 02/50] =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=AB=99CDN=E6=9B=B4?=
=?UTF-8?q?=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
工具站CDN更新
---
README.md | 23 +++++++++++--------
.../src/main/resources/application-bejson.yml | 2 +-
.../src/main/resources/application-dev.yml | 2 +-
.../main/resources/application-devtools.yml | 2 +-
.../src/main/resources/statics/version.json | 2 +-
.../main/resources/templates/header-CDN.html | 18 +++++++--------
6 files changed, 26 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
index 31b97022..6809e109 100644
--- a/README.md
+++ b/README.md
@@ -39,28 +39,31 @@
- 可设置`表名前缀`,例如sys_user前缀为sys_之后可以正确生成user类
- 可在`applicaltion.yml`中的`OEM.mode`设置`js/css引入模式`为`local`(本地模式,默认)/`CDN`(云CDN模式,在线网站推荐,省流量)
- OEM信息可以在`applicaltion.yml`中的`OEM`中更改
+- *支持公共js/css的Local/CDN模式切换,方便`本地`或者`工具站`进行部署,可以在`application.yml`的`OEM.Mode=`进行设置,之后请在`header-CDN.html`/`header-local.html`中检查对应js/css配置是否正确。
# Url
感谢`卡卡`将他部署在[BEJSON](https://java.bejson.com/generator)上,目前是besjon专供的金牌工具(线上版本不一定是最新的,会有延迟,请谅解,谢谢).
感谢`jully.top`部署的副本 [https://jully.top/generator/](https://jully.top/generator/)。
-感谢`三叔`将他部署在[DEVTOOLS](https://java.devtools.cn/)上,继续作为Golden Tool开放给大家使用。
-
+感谢`三叔`将他部署在[DEVTOOLS](https://java.devtools.cn/) (Demised)上,继续作为Golden Tool开放给大家使用。
+感谢`七牛`提供的云js/css免费加速服务,它尽可能全面收录优秀的开源库,并免费为之提供 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) .
-| 访问地址 | http://localhost:1234/generator |
-|:--------------|:--------------------------------------------------------------|
-| BEJSON 在线地址 | https://java.bejson.com/generator |
-| Jully 在线地址 | https://jully.top/generator/ |
-| DEVTOOLS 在线地址 | https://java.devtools.cn |
-| CSDN BLOG | https://zhengkai.blog.csdn.net |
-| GITEE仓库 | https://gitee.com/moshowgame/SpringBootCodeGenerator/releases |
-| GITHUB仓库 | https://github.com/moshowgame/SpringBootCodeGenerator |
+| 访问地址 | http://localhost:1234/generator |
+|:-----------------------|:--------------------------------------------------------------|
+| BEJSON 在线地址 | https://java.bejson.com/generator |
+| Jully 在线地址 | https://jully.top/generator/ |
+| DEVTOOLS 在线地址(Demised) | https://java.devtools.cn |
+| CSDN BLOG | https://zhengkai.blog.csdn.net |
+| GITEE仓库 | https://gitee.com/moshowgame/SpringBootCodeGenerator/releases |
+| GITHUB仓库 | https://github.com/moshowgame/SpringBootCodeGenerator |
# Update Logs
| 更新日期 | 更新内容 |
|:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 2023.10.22 | 工具站CDN更新。 |
+| 2023.08.31 | (感谢@Nisus-Liu的PR)
fix 驼峰列名转命名风格错误问题
增强转下划线命名风格, 对原始风格不敏感. 支持各种命名风格的列名 to 下划线
增加 NonCaseString 大小写不敏感字符串包装类, 简化编码
几点代码小优化。 |
| 2023.07.11 | 安全更新,正式支持SpringBoot3,javax升级到jakarta。 |
| 2023.01.02 | 新增TkMybatis模板(感谢@sgj666的建议)。 |
| 2023.01.01 | 新增GCP BigQuery/Dataflow JJS/QlikSense BI模板。 |
diff --git a/generator-web/src/main/resources/application-bejson.yml b/generator-web/src/main/resources/application-bejson.yml
index 0042c8df..1ecf3888 100644
--- a/generator-web/src/main/resources/application-bejson.yml
+++ b/generator-web/src/main/resources/application-bejson.yml
@@ -47,7 +47,7 @@ spring:
#mvc:
# static-path-pattern: /statics/**
OEM:
- version: 2023.7
+ version: 2023.10
header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA在线代码生成
diff --git a/generator-web/src/main/resources/application-dev.yml b/generator-web/src/main/resources/application-dev.yml
index b152d729..5be7d725 100644
--- a/generator-web/src/main/resources/application-dev.yml
+++ b/generator-web/src/main/resources/application-dev.yml
@@ -47,7 +47,7 @@ spring:
#mvc:
# static-path-pattern: /statics/**
OEM:
- version: 2023.7
+ version: 2023.10
header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA代码生成平台
diff --git a/generator-web/src/main/resources/application-devtools.yml b/generator-web/src/main/resources/application-devtools.yml
index a3101628..8e447a8b 100644
--- a/generator-web/src/main/resources/application-devtools.yml
+++ b/generator-web/src/main/resources/application-devtools.yml
@@ -47,7 +47,7 @@ spring:
#mvc:
# static-path-pattern: /statics/**
OEM:
- version: 2023.7
+ version: 2023.10
header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA在线代码生成
diff --git a/generator-web/src/main/resources/statics/version.json b/generator-web/src/main/resources/statics/version.json
index 7a0ed972..deefb3d9 100644
--- a/generator-web/src/main/resources/statics/version.json
+++ b/generator-web/src/main/resources/statics/version.json
@@ -1 +1 @@
-{"version": "20201222"}
\ No newline at end of file
+{"version": "20231022"}
\ No newline at end of file
diff --git a/generator-web/src/main/resources/templates/header-CDN.html b/generator-web/src/main/resources/templates/header-CDN.html
index 3cb77951..ce5c55a6 100644
--- a/generator-web/src/main/resources/templates/header-CDN.html
+++ b/generator-web/src/main/resources/templates/header-CDN.html
@@ -5,7 +5,7 @@
-
+
@@ -19,15 +19,15 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
From 3af7114c7ffd9cb3bc5f2229d699cd8473a5c40f Mon Sep 17 00:00:00 2001
From: moshow
Date: Sun, 22 Oct 2023 15:06:59 +0800
Subject: [PATCH 03/50] bejson url update
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 6809e109..8e455e44 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@ Thanks for `JetBrains` providing us the `Licenses for Open Source Development`
| 访问地址 | http://localhost:1234/generator |
|:-----------------------|:--------------------------------------------------------------|
-| BEJSON 在线地址 | https://java.bejson.com/generator |
+| BEJSON 在线地址 | https://java.bejson.com/generator/ |
| Jully 在线地址 | https://jully.top/generator/ |
| DEVTOOLS 在线地址(Demised) | https://java.devtools.cn |
| CSDN BLOG | https://zhengkai.blog.csdn.net |
From 536ab42ec19142622c08e47600e965e85fa23261 Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Sat, 16 Dec 2023 16:43:41 +0000
Subject: [PATCH 04/50] vuln-fix: Use HTTPS instead of HTTP to resolve deps
CVE-2021-26291
This fixes a security vulnerability in this project where the `pom.xml`
files were configuring Maven to resolve dependencies over HTTP instead of
HTTPS.
Weakness: CWE-829: Inclusion of Functionality from Untrusted Control Sphere
Severity: High
CVSS: 8.1
Detection: CodeQL & OpenRewrite (https://app.moderne.io/recipes/org.openrewrite.maven.security.UseHttpsForRepositories)
Reported-by: Jonathan Leitschuh
Signed-off-by: Jonathan Leitschuh
Bug-tracker: https://github.com/JLLeitschuh/security-research/issues/8
Detection: CodeQL (https://codeql.github.com/codeql-query-help/java/java-maven-non-https-url/) & OpenRewrite (https://app.moderne.io/recipes/org.openrewrite.maven.security.UseHttpsForRepositories)
Reported-by: Jonathan Leitschuh
Signed-off-by: Jonathan Leitschuh
Bug-tracker: https://github.com/JLLeitschuh/security-research/issues/8
Use this link to re-run the recipe: https://app.moderne.io/recipes/builder/IfHkrYfxx?organizationId=QWxsIEdpdEh1Yg%3D%3D
Co-authored-by: Moderne
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 926d3dac..09ae37a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,7 +131,7 @@
alimaven
aliyun maven
- http://maven.aliyun.com/nexus/content/groups/public/
+ https://maven.aliyun.com/nexus/content/groups/public/
From 64fbaade243d27b3ac0a97b73c6e028292a18553 Mon Sep 17 00:00:00 2001
From: L&J <609069481@qq.com>
Date: Wed, 24 Jan 2024 22:02:23 +0800
Subject: [PATCH 05/50] =?UTF-8?q?fix:=20=E5=A4=A7=E5=86=99=E4=B8=8B?=
=?UTF-8?q?=E6=BB=91=E4=B8=8B=E5=88=97=E5=90=8D=E8=BD=AC=E9=A9=BC=E5=B3=B0?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修改前: CREATE_TIME -> cREATETIME
修改后: CREATE_TIME -> createTime
---
.../java/com/softdev/system/generator/util/StringUtils.java | 2 +-
generator-web/src/test/java/FooTest.java | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java b/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
index 061d94ae..b1fdeb4f 100644
--- a/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
+++ b/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
@@ -47,7 +47,7 @@ public static String underlineToCamelCase(String underscoreName) {
result.append(Character.toUpperCase(ch));
flag = false;
} else {
- result.append(ch);
+ result.append(Character.toLowerCase(ch));
}
}
}
diff --git a/generator-web/src/test/java/FooTest.java b/generator-web/src/test/java/FooTest.java
index 1a9254fe..bbdff214 100644
--- a/generator-web/src/test/java/FooTest.java
+++ b/generator-web/src/test/java/FooTest.java
@@ -19,6 +19,8 @@ public static void main(String[] args) {
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"));
}
From 48054f3a6b99fd3648a33b2654d3256334065c46 Mon Sep 17 00:00:00 2001
From: L&J <609069481@qq.com>
Date: Sat, 27 Jan 2024 00:05:02 +0800
Subject: [PATCH 06/50] =?UTF-8?q?fix:=20=E5=A4=A7=E5=86=99=E4=B8=8B?=
=?UTF-8?q?=E6=BB=91=E4=B8=8B=E5=88=97=E5=90=8D=E8=BD=AC=E9=A9=BC=E5=B3=B0?=
=?UTF-8?q?=E9=97=AE=E9=A2=98,=20=E6=96=B0=E5=A2=9EtoLowerCamel=20?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=E6=90=9E=E5=AE=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修改前: CREATE_TIME -> cREATETIME
修改后: CREATE_TIME -> createTime
---
generator-web/pom.xml | 5 +-
.../system/generator/util/StringUtils.java | 40 ++++++++-
.../system/generator/util/TableParseUtil.java | 10 +--
.../generator/util/StringUtilsTest.java | 81 +++++++++++++++++++
4 files changed, 124 insertions(+), 12 deletions(-)
create mode 100644 generator-web/src/test/java/com/softdev/system/generator/util/StringUtilsTest.java
diff --git a/generator-web/pom.xml b/generator-web/pom.xml
index c6ace661..be74e21b 100644
--- a/generator-web/pom.xml
+++ b/generator-web/pom.xml
@@ -36,10 +36,11 @@
spring-boot-starter-data-jpa
-->
-
+ test
+
org.springframework.boot
diff --git a/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java b/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
index b1fdeb4f..4274c881 100644
--- a/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
+++ b/generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java
@@ -14,6 +14,9 @@ public class StringUtils {
* @return
*/
public static String upperCaseFirst(String str) {
+ if (str == null || str.trim().isEmpty()) {
+ return str;
+ }
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
@@ -47,7 +50,7 @@ public static String underlineToCamelCase(String underscoreName) {
result.append(Character.toUpperCase(ch));
flag = false;
} else {
- result.append(Character.toLowerCase(ch));
+ result.append(ch);
}
}
}
@@ -89,12 +92,41 @@ public static String toUnderline(String str, boolean upperCase) {
return result.toString();
}
+ /**
+ * any str ==> lowerCamel
+ */
+ public static String toLowerCamel(String str) {
+ if (str == null || str.trim().isEmpty()) {
+ return str;
+ }
- public static boolean isNotNull(String str){
- return org.apache.commons.lang3.StringUtils.isNotEmpty(str);
+ StringBuilder result = new StringBuilder();
+ char pre = '\0';
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ if (ch == '-' || ch == '—' || ch == '_') {
+ ch = '_';
+ pre = ch;
+ continue;
+ }
+ char ch2 = ch;
+ if (pre == '_') {
+ ch2 = Character.toUpperCase(ch);
+ pre = ch2;
+ } else if (pre >= 'A' && pre <= 'Z') {
+ pre = ch;
+ ch2 = Character.toLowerCase(ch);
+ } else {
+ pre = ch;
+ }
+ result.append(ch2);
+ }
+
+ return lowerCaseFirst(result.toString());
}
- public static void main(String[] args) {
+ public static boolean isNotNull(String str) {
+ return org.apache.commons.lang3.StringUtils.isNotEmpty(str);
}
}
diff --git a/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java b/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java
index 7104ad83..3e30dcc6 100644
--- a/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java
+++ b/generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java
@@ -164,7 +164,7 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
// 2019-2-22 zhengkai 要在条件中使用复杂的表达式
// 2019-4-29 zhengkai 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 )
// 2020-10-20 zhengkai 优化对fulltext/index关键字的处理(感谢@WEGFan的反馈)
- // 2023-8-27 zhangfei 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
+ // 2023-8-27 L&J 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
boolean notSpecialFlag = isNotSpecialColumnLine(columnLine, i);
if (notSpecialFlag) {
@@ -185,13 +185,11 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
// field Name
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
- // 2023-8-27 zhangfei 支持原始列名任意命名风格, 不依赖用户是否输入下划线
+ // 2023-8-27 L&J 支持原始列名任意命名风格, 不依赖用户是否输入下划线
String fieldName = null;
if (ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)) {
- fieldName = StringUtils.lowerCaseFirst(StringUtils.underlineToCamelCase(columnName));
- if (fieldName.contains("_")) {
- fieldName = fieldName.replaceAll("_", "");
- }
+ // 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)) {
diff --git a/generator-web/src/test/java/com/softdev/system/generator/util/StringUtilsTest.java b/generator-web/src/test/java/com/softdev/system/generator/util/StringUtilsTest.java
new file mode 100644
index 00000000..b7fbdca1
--- /dev/null
+++ b/generator-web/src/test/java/com/softdev/system/generator/util/StringUtilsTest.java
@@ -0,0 +1,81 @@
+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(""));
+ }
+}
From 5397cd122142098f6e6092ebe9248253cc199af0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Moshow=E9=83=91=E9=94=B4?=
Date: Sat, 20 Apr 2024 16:34:58 +0800
Subject: [PATCH 07/50] =?UTF-8?q?|=202024.04.21=20|=20=E4=BF=AE=E5=A4=8DCD?=
=?UTF-8?q?N=E7=89=88=E6=9C=ACcdn.staticfile.org=E5=9F=9F=E5=90=8D?=
=?UTF-8?q?=E5=A4=87=E4=BB=BD=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98=EF=BC=8C?=
=?UTF-8?q?=E5=B7=B2=E5=90=8C=E6=AD=A5=E6=9B=B4=E6=96=B0=E5=88=B0cdn.stati?=
=?UTF-8?q?cfile.net=EF=BC=88=E6=9C=AC=E5=9C=B0=E7=89=88=E6=9C=AC=E5=88=99?=
=?UTF-8?q?=E4=B8=8D=E5=8F=97=E5=BD=B1=E5=93=8D=EF=BC=89=20|=202024.01.26?=
=?UTF-8?q?=20|=20=E4=BF=AE=E5=A4=8D=E5=A4=A7=E5=86=99=E4=B8=8B=E6=BB=91?=
=?UTF-8?q?=E7=BA=BF=E5=88=97=E5=90=8D=E8=BD=AC=E9=A9=BC=E5=B3=B0=E9=97=AE?=
=?UTF-8?q?=E9=A2=98=EF=BC=88=E6=84=9F=E8=B0=A2@Nisus-Liu=20=E7=9A=84PR?=
=?UTF-8?q?=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
| 2024.04.21 | 修复CDN版本cdn.staticfile.org域名备份失败问题,已同步更新到cdn.staticfile.net(本地版本则不受影响)
| 2024.01.26 | 修复大写下滑线列名转驼峰问题(感谢@Nisus-Liu
的PR)
---
README.md | 57 ++++++++++--------
.../src/main/resources/application-bejson.yml | 2 +-
.../src/main/resources/application-dev.yml | 2 +-
.../main/resources/application-devtools.yml | 2 +-
.../src/main/resources/application.yml | 2 +-
.../main/resources/templates/header-CDN.html | 32 +++++-----
site_analysis-2024.png | Bin 0 -> 244784 bytes
7 files changed, 52 insertions(+), 45 deletions(-)
create mode 100644 site_analysis-2024.png
diff --git a/README.md b/README.md
index 8e455e44..dd4c5eeb 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# SpringBootCodeGenerator
----
-又名`JAVA在线代码生成平台`、`sql转java`、`大狼狗代码生成器`、`mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`
+又名`Java代码生成器`、`JAVA在线代码生成平台`、`sql转java`、`大狼狗代码生成器`、`mybatis在线生成器`、`SQL转Java JPA、MYBATIS实现类代码生成平台`



@@ -16,38 +16,28 @@
>For reducing the repetitive CRUD work
> #以解放双手为目的,减少大量的`重复CRUD工作`
>
->mainly support mysql, support oracle and pgsql as well
+>Support mysql, oracle and pgsql
> #支持`MySQL`、Oracle、PgSQL三大主流数据库
>
->generate to many popular templates by ddl-sql/insert-sql/simple json
-> 可通过`建表SQL语句`或`INSERT语句`或者`简单JSON`生成`JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper`相关模板代码.
+>Generate to many predefined popular templates by DDL-SQL/Insert-SQL/Simple JSON
+> 可通过`建表SQL语句`或`INSERT语句`或者`简单JSON`生成预设的`JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL/CommonMapper`相关模板代码.
>
->thanks for your using and feedback,I'm inspired by the 600PV every day and github more than 900 stars
-> 感谢大家的使用和反馈,每天六百的PV和获得超过九百多的星星是我前进和继续做下去的动力。
+>Thanks for your using and feedback,I'm inspired by the 1500+PV (AVG) every day and github more than 1.9K stars
+> 感谢大家的使用和反馈,每天1500的PV和获得超过九百多的星星是我前进和继续做下去的动力。
>
->hope everyone can keep good balance on work and life , stay health and safety , be smooth on work as well
-> 愿大家可以维持生活和工作平衡,保持健康和安全,祝大家工作顺利!
+>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.
+> 愿大家可以维持生活和工作平衡,保持健康和安全,祝大家工作顺利,步步高升!
+>Please submit your issue and template , or pull your good idea into the PR
+> 提交你的问题和生成模板,或者提交你的好主意到PR。
-# Tips or Features
-- 支持`DDL SQL`/`INSERT SQL`/`SIMPLE JSON`三种生成模式
-- `自动记忆`最近生成的内容,最多保留9个
-- 提供众多`通用模板`,易于使用,复制粘贴加简单修改即可完成CRUD操作
-- 支持`特殊字符`模板(`#`请用`井`代替;`$`请用`¥`代替)
-- `Util集合`提供一些基本对象的使用方法供方便COPY,如对应的CRUD SQL语句、setMap、getMap、get属性等等
-- 关于`类名注释`,可根据`comment=(mysql)`或者`comment on table(pgsql/oracle)`生成
-- 可设置是否`自动引包`(java中的import)及`引入包路径`(java类中的package),建议取消并配合IDEA的自动引包更智能(Settings→Editor→General→Auto Import,勾选Add unambiguous imports on the fly以及Optimize imports on the fly)。
-- 可设置`表名前缀`,例如sys_user前缀为sys_之后可以正确生成user类
-- 可在`applicaltion.yml`中的`OEM.mode`设置`js/css引入模式`为`local`(本地模式,默认)/`CDN`(云CDN模式,在线网站推荐,省流量)
-- OEM信息可以在`applicaltion.yml`中的`OEM`中更改
-- *支持公共js/css的Local/CDN模式切换,方便`本地`或者`工具站`进行部署,可以在`application.yml`的`OEM.Mode=`进行设置,之后请在`header-CDN.html`/`header-local.html`中检查对应js/css配置是否正确。
# Url
-感谢`卡卡`将他部署在[BEJSON](https://java.bejson.com/generator)上,目前是besjon专供的金牌工具(线上版本不一定是最新的,会有延迟,请谅解,谢谢).
-感谢`jully.top`部署的副本 [https://jully.top/generator/](https://jully.top/generator/)。
-感谢`三叔`将他部署在[DEVTOOLS](https://java.devtools.cn/) (Demised)上,继续作为Golden Tool开放给大家使用。
-感谢`七牛`提供的云js/css免费加速服务,它尽可能全面收录优秀的开源库,并免费为之提供 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) .
+- 感谢`卡卡`将他部署在[BEJSON](https://java.bejson.com/generator)上,目前是besjon专供的`金牌工具`(线上版本不一定是最新的,会有延迟,请谅解,谢谢).
+- 感谢`jully.top`部署的副本 [https://jully.top/generator/](https://jully.top/generator/)。
+- 感谢`三叔`将他部署在[DEVTOOLS](https://java.devtools.cn/) (Demised)上,继续作为Golden Tool开放给大家使用。
+- 感谢`七牛`提供的云js/css免费加速服务,它尽可能全面收录优秀的开源库,并免费为之提供 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) .
| 访问地址 | http://localhost:1234/generator |
|:-----------------------|:--------------------------------------------------------------|
@@ -58,10 +48,26 @@ Thanks for `JetBrains` providing us the `Licenses for Open Source Development`
| GITEE仓库 | https://gitee.com/moshowgame/SpringBootCodeGenerator/releases |
| GITHUB仓库 | https://github.com/moshowgame/SpringBootCodeGenerator |
+# Tips or Features
+- 支持`DDL SQL`/`INSERT SQL`/`SIMPLE JSON`三种生成模式
+- `自动记忆`最近生成的内容,最多保留9个
+- 提供众多`通用模板`,易于使用,复制粘贴加简单修改即可完成CRUD操作
+- 支持`特殊字符`模板(`#`请用`井`代替;`$`请用`¥`代替)
+- `Util集合`提供一些基本对象的使用方法供方便COPY,如对应的CRUD SQL语句、setMap、getMap、get属性等等
+- 关于`类名注释`,可根据`comment=(mysql)`或者`comment on table(pgsql/oracle)`生成
+- 可设置是否`自动引包`(java中的import)及`引入包路径`(java类中的package),建议取消并配合IDEA的自动引包更智能(Settings→Editor→General→Auto Import,勾选Add unambiguous imports on the fly以及Optimize imports on the fly)。
+- 可设置`表名前缀`,例如sys_user前缀为sys_之后可以正确生成user类
+- 可在`applicaltion.yml`中的`OEM.mode`设置`js/css引入模式`为`local`(本地模式,默认)/`CDN`(云CDN模式,在线网站推荐,省流量)
+- OEM信息可以在`applicaltion.yml`中的`OEM`中更改
+- *支持公共js/css的Local/CDN模式切换,方便`本地`或者`工具站`进行部署,可以在`application.yml`的`OEM.Mode=`进行设置,之后请在`header-CDN.html`/`header-local.html`中检查对应js/css配置是否正确。
+
# Update Logs
| 更新日期 | 更新内容 |
|:-----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 2024.04.21 | 修复CDN版本cdn.staticfile.org域名备份失败问题,已同步更新到cdn.staticfile.net(本地版本则不受影响)
+| 2024.01.26 | 修复大写下滑线列名转驼峰问题(感谢@Nisus-Liu
+的PR) |
| 2023.10.22 | 工具站CDN更新。 |
| 2023.08.31 | (感谢@Nisus-Liu的PR)
fix 驼峰列名转命名风格错误问题
增强转下划线命名风格, 对原始风格不敏感. 支持各种命名风格的列名 to 下划线
增加 NonCaseString 大小写不敏感字符串包装类, 简化编码
几点代码小优化。 |
| 2023.07.11 | 安全更新,正式支持SpringBoot3,javax升级到jakarta。 |
@@ -161,6 +167,7 @@ Thanks for `JetBrains` providing us the `Licenses for Open Source Development`
+
diff --git a/generator-web/src/main/resources/application-bejson.yml b/generator-web/src/main/resources/application-bejson.yml
index 1ecf3888..dfc4a0ab 100644
--- a/generator-web/src/main/resources/application-bejson.yml
+++ b/generator-web/src/main/resources/application-bejson.yml
@@ -47,7 +47,7 @@ spring:
#mvc:
# static-path-pattern: /statics/**
OEM:
- version: 2023.10
+ version: 2024.4
header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA在线代码生成
diff --git a/generator-web/src/main/resources/application-dev.yml b/generator-web/src/main/resources/application-dev.yml
index 5be7d725..9f1187b0 100644
--- a/generator-web/src/main/resources/application-dev.yml
+++ b/generator-web/src/main/resources/application-dev.yml
@@ -47,7 +47,7 @@ spring:
#mvc:
# static-path-pattern: /statics/**
OEM:
- version: 2023.10
+ version: 2024.4
header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA代码生成平台
diff --git a/generator-web/src/main/resources/application-devtools.yml b/generator-web/src/main/resources/application-devtools.yml
index 8e447a8b..b04fa670 100644
--- a/generator-web/src/main/resources/application-devtools.yml
+++ b/generator-web/src/main/resources/application-devtools.yml
@@ -47,7 +47,7 @@ spring:
#mvc:
# static-path-pattern: /statics/**
OEM:
- version: 2023.10
+ version: 2024.4
header: SQL转Java JPA、MYBATIS实现类代码生成平台
keywords: sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现
title: JAVA在线代码生成
diff --git a/generator-web/src/main/resources/application.yml b/generator-web/src/main/resources/application.yml
index caf4dfcd..6857c9dc 100644
--- a/generator-web/src/main/resources/application.yml
+++ b/generator-web/src/main/resources/application.yml
@@ -1,3 +1,3 @@
spring:
profiles:
- active: dev
\ No newline at end of file
+ active: bejson
\ No newline at end of file
diff --git a/generator-web/src/main/resources/templates/header-CDN.html b/generator-web/src/main/resources/templates/header-CDN.html
index ce5c55a6..8f173bff 100644
--- a/generator-web/src/main/resources/templates/header-CDN.html
+++ b/generator-web/src/main/resources/templates/header-CDN.html
@@ -3,31 +3,31 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/site_analysis-2024.png b/site_analysis-2024.png
new file mode 100644
index 0000000000000000000000000000000000000000..9abd8fb103ec3424adb4d2fda5f4292d43f7a472
GIT binary patch
literal 244784
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%0AlB
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