Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e008e4d

Browse files
fix: #143 驼峰列名转命名风格错误问题
1. fix #143 2. 增强命名风格转换, 对原始风格不敏感. 支持各种命名风格的列名 2. 附带增加 NonCaseString 大小写不敏感字符串包装类, 简化编码 3. 几点代码小优化
1 parent 17d668a commit e008e4d

File tree

6 files changed

+265
-28
lines changed

6 files changed

+265
-28
lines changed

‎generator-web/pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
<properties>
1818
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1919
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
20-
<java.version>1.8</java.version>
2120
</properties>
2221

2322
<dependencies>
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package com.softdev.system.generator.entity;
2+
3+
import lombok.AllArgsConstructor;
4+
5+
/**
6+
* String 包装类
7+
* <p>
8+
* 忽略大小写
9+
**考虑增加这个类是, 如果在 StringUtils 中加工具方法, 使用起来代码非常冗长且不方便
10+
* @author Nisus
11+
* @see String
12+
*/
13+
@AllArgsConstructor
14+
public class NonCaseString implements CharSequence {
15+
private String value;
16+
17+
public static NonCaseString of(String str) {
18+
assert str != null;
19+
return new NonCaseString(str);
20+
}
21+
22+
23+
/**
24+
* {@link String#indexOf(String)} 增强, 忽略大小写
25+
*/
26+
public int indexOf(String m) {
27+
String text = this.value;
28+
if (text == null || m == null || text.length() < m.length()) {
29+
return -1;
30+
}
31+
return text.toLowerCase().indexOf(m.toLowerCase());
32+
}
33+
34+
/**
35+
* {@link String#lastIndexOf(String)} 增强, 忽略大小写
36+
*/
37+
public int lastIndexOf(String m) {
38+
String text = this.value;
39+
if (text == null || m == null || text.length() < m.length()) {
40+
return -1;
41+
}
42+
return text.toLowerCase().lastIndexOf(m.toLowerCase());
43+
}
44+
45+
/**
46+
* 是否包含, 大小写不敏感
47+
* <pre
48+
* "abcxyz" 包含 "abc" => true
49+
* "abcxyz" 包含 "ABC" => true
50+
* "abcxyz" 包含 "aBC" => true
51+
* </pre>
52+
*
53+
* @param m 被包含字符串
54+
*/
55+
public boolean contains(String m) {
56+
String text = this.value;
57+
if (text.length() < m.length()) {
58+
return false;
59+
}
60+
return text.toLowerCase().contains(m.toLowerCase());
61+
}
62+
63+
/**
64+
* 任意一个包含返回true
65+
* <pre>
66+
* containsAny("abcdef", "a", "b)
67+
* 等价
68+
* "abcdef".contains("a") || "abcdef".contains("b")
69+
* </pre>
70+
*
71+
* @param matchers 多个要判断的被包含项
72+
*/
73+
public boolean containsAny(String... matchers) {
74+
for (String matcher : matchers) {
75+
if (contains(matcher)) {
76+
return true;
77+
}
78+
}
79+
return false;
80+
}
81+
82+
/**
83+
* 所有都包含才返回true
84+
*
85+
* @param matchers 多个要判断的被包含项
86+
*/
87+
public boolean containsAllIgnoreCase(String... matchers) {
88+
for (String matcher : matchers) {
89+
if (contains(matcher) == false) {
90+
return false;
91+
}
92+
}
93+
return true;
94+
}
95+
96+
public NonCaseString trim() {
97+
return NonCaseString.of(this.value.trim());
98+
}
99+
100+
public NonCaseString replace(char oldChar, char newChar) {
101+
return NonCaseString.of(this.value.replace(oldChar, newChar));
102+
}
103+
104+
public NonCaseString replaceAll(String regex, String replacement) {
105+
return NonCaseString.of(this.value.replaceAll(regex, replacement));
106+
}
107+
108+
public NonCaseString substring(int beginIndex) {
109+
return NonCaseString.of(this.value.substring(beginIndex));
110+
}
111+
112+
public NonCaseString substring(int beginIndex, int endIndex) {
113+
return NonCaseString.of(this.value.substring(beginIndex, endIndex));
114+
}
115+
116+
public boolean isNotEmpty() {
117+
return !this.value.isEmpty();
118+
}
119+
120+
@Override
121+
public int length() {
122+
return this.value.length();
123+
}
124+
125+
@Override
126+
public char charAt(int index) {
127+
return this.value.charAt(index);
128+
}
129+
130+
131+
@Override
132+
public CharSequence subSequence(int start, int end) {
133+
return this.value.subSequence(start, end);
134+
}
135+
136+
public String[] split(String regex) {
137+
return this.value.split(regex);
138+
}
139+
140+
141+
/**
142+
* @return 原始字符串
143+
*/
144+
public String get() {
145+
return this.value;
146+
}
147+
148+
@Override
149+
public String toString() {
150+
return this.value;
151+
}
152+
}

‎generator-web/src/main/java/com/softdev/system/generator/util/StringUtils.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static String underlineToCamelCase(String underscoreName) {
4040
boolean flag = false;
4141
for (int i = 0; i < underscoreName.length(); i++) {
4242
char ch = underscoreName.charAt(i);
43-
if ("_".charAt(0) == ch) {
43+
if ('_' == ch) {
4444
flag = true;
4545
} else {
4646
if (flag) {
@@ -54,6 +54,42 @@ public static String underlineToCamelCase(String underscoreName) {
5454
}
5555
return result.toString();
5656
}
57+
58+
/**
59+
* 转 user_name 风格
60+
*
61+
* 不管原始是什么风格
62+
*/
63+
public static String toUnderline(String str, boolean upperCase) {
64+
if (str == null || str.trim().isEmpty()) {
65+
return str;
66+
}
67+
68+
StringBuilder result = new StringBuilder();
69+
boolean preIsUnderscore = false;
70+
for (int i = 0; i < str.length(); i++) {
71+
char ch = str.charAt(i);
72+
if (ch == '_') {
73+
preIsUnderscore = true;
74+
} else if (ch == '-') {
75+
ch = '_';
76+
preIsUnderscore = true; // -A -> _a
77+
} else if (ch >= 'A' && ch <= 'Z') {
78+
// A -> _a
79+
if (!preIsUnderscore && i > 0) { // _A -> _a
80+
result.append("_");
81+
}
82+
preIsUnderscore = false;
83+
} else {
84+
preIsUnderscore = false;
85+
}
86+
result.append(upperCase ? Character.toUpperCase(ch) : Character.toLowerCase(ch));
87+
}
88+
89+
return result.toString();
90+
}
91+
92+
5793
public static boolean isNotNull(String str){
5894
return org.apache.commons.lang3.StringUtils.isNotEmpty(str);
5995
}

‎generator-web/src/main/java/com/softdev/system/generator/util/TableParseUtil.java

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package com.softdev.system.generator.util;
22

3-
import com.softdev.system.generator.util.mysqlJavaTypeUtil;
43
import com.alibaba.fastjson.JSON;
54
import com.alibaba.fastjson.JSONArray;
65
import com.alibaba.fastjson.JSONObject;
76
import com.softdev.system.generator.entity.ClassInfo;
87
import com.softdev.system.generator.entity.FieldInfo;
8+
import com.softdev.system.generator.entity.NonCaseString;
99
import com.softdev.system.generator.entity.ParamInfo;
1010

1111
import java.io.IOException;
12-
import java.math.BigDecimal;
1312
import java.util.ArrayList;
1413
import java.util.Arrays;
15-
import java.util.Date;
1614
import java.util.List;
1715
import java.util.concurrent.atomic.AtomicInteger;
1816
import java.util.regex.Matcher;
@@ -34,23 +32,28 @@ public class TableParseUtil {
3432
public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
3533
throws IOException {
3634
//process the param
37-
String tableSql = paramInfo.getTableSql();
35+
NonCaseString tableSql = NonCaseString.of(paramInfo.getTableSql());
3836
String nameCaseType = MapUtil.getString(paramInfo.getOptions(),"nameCaseType");
3937
Boolean isPackageType = MapUtil.getBoolean(paramInfo.getOptions(),"isPackageType");
4038

4139
if (tableSql == null || tableSql.trim().length() == 0) {
4240
throw new CodeGenerateException("Table structure can not be empty. 表结构不能为空。");
4341
}
4442
//deal with special character
45-
tableSql = tableSql.trim().replaceAll("'", "`").replaceAll("\"", "`").replaceAll(",", ",").toLowerCase();
43+
tableSql = tableSql.trim()
44+
.replaceAll("'", "`")
45+
.replaceAll("\"", "`")
46+
.replaceAll(",", ",")
47+
// 这里全部转小写, 会让驼峰风格的字段名丢失驼峰信息(真有驼峰sql字段名的呢(* ̄) ̄)); 下文使用工具方法处理包含等
48+
// .toLowerCase()
49+
;
4650
//deal with java string copy \n"
4751
tableSql = tableSql.trim().replaceAll("\\\\n`", "").replaceAll("\\+", "").replaceAll("``", "`").replaceAll("\\\\", "");
4852
// table Name
4953
String tableName = null;
50-
if (tableSql.contains("TABLE") && tableSql.contains("(")) {
51-
tableName = tableSql.substring(tableSql.indexOf("TABLE") + 5, tableSql.indexOf("("));
52-
} else if (tableSql.contains("table") && tableSql.contains("(")) {
53-
tableName = tableSql.substring(tableSql.indexOf("table") + 5, tableSql.indexOf("("));
54+
int tableKwIx = tableSql.indexOf("TABLE"); // 包含判断和位置一次搞定
55+
if (tableKwIx > -1 && tableSql.contains("(")) {
56+
tableName = tableSql.substring(tableKwIx + 5, tableSql.indexOf("(")).get();
5457
} else {
5558
throw new CodeGenerateException("Table structure incorrect.表结构不正确。");
5659
}
@@ -88,9 +91,11 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
8891
String classComment = null;
8992
//mysql是comment=,pgsql/oracle是comment on table,
9093
//2020-05-25 优化表备注的获取逻辑
91-
if (tableSql.contains("comment=") || tableSql.contains("comment on table")) {
92-
String classCommentTmp = (tableSql.contains("comment=")) ?
93-
tableSql.substring(tableSql.lastIndexOf("comment=") + 8).trim() : tableSql.substring(tableSql.lastIndexOf("comment on table") + 17).trim();
94+
if (tableSql.containsAny("comment=", "comment on table")) {
95+
int ix = tableSql.lastIndexOf("comment=");
96+
String classCommentTmp = (ix > -1) ?
97+
tableSql.substring(ix + 8).trim().get() :
98+
tableSql.substring(tableSql.lastIndexOf("comment on table") + 17).trim().get();
9499
if (classCommentTmp.contains("`")) {
95100
classCommentTmp = classCommentTmp.substring(classCommentTmp.indexOf("`") + 1);
96101
classCommentTmp = classCommentTmp.substring(0, classCommentTmp.indexOf("`"));
@@ -109,7 +114,7 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
109114
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
110115

111116
// 正常( ) 内的一定是字段相关的定义。
112-
String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")"));
117+
String fieldListTmp = tableSql.substring(tableSql.indexOf("(") + 1, tableSql.lastIndexOf(")")).get();
113118

114119
// 匹配 comment,替换备注里的小逗号, 防止不小心被当成切割符号切割
115120
String commentPattenStr1 = "comment `(.*?)\\`";
@@ -149,7 +154,8 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
149154
if (fieldLineList.length > 0) {
150155
int i = 0;
151156
//i为了解决primary key关键字出现的地方,出现在前3行,一般和id有关
152-
for (String columnLine : fieldLineList) {
157+
for (String columnLine0 : fieldLineList) {
158+
NonCaseString columnLine = NonCaseString.of(columnLine0);
153159
i++;
154160
columnLine = columnLine.replaceAll("\n", "").replaceAll("\t", "").trim();
155161
// `userid` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
@@ -158,13 +164,10 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
158164
// 2019年2月22日 zhengkai 要在条件中使用复杂的表达式
159165
// 2019年4月29日 zhengkai 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 )
160166
// 2020年10月20日 zhengkai 优化对fulltext/index关键字的处理(感谢@WEGFan的反馈)
161-
boolean specialFlag = (!columnLine.contains("key ") && !columnLine.contains("constraint") && !columnLine.contains("using") && !columnLine.contains("unique ")
162-
&& !(columnLine.contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
163-
&& !columnLine.contains("fulltext ") && !columnLine.contains("index ")
164-
&& !columnLine.contains("pctincrease")
165-
&& !columnLine.contains("buffer_pool") && !columnLine.contains("tablespace")
166-
&& !(columnLine.contains("primary ") && i > 3));
167-
if (specialFlag) {
167+
// 2023年8月27日 zhangfei 改用工具方法判断, 且修改变量名(非特殊标识), 方法抽取
168+
boolean notSpecialFlag = isNotSpecialColumnLine(columnLine, i);
169+
170+
if (notSpecialFlag) {
168171
//如果是oracle的number(x,x),可能出现最后分割残留的,x),这里做排除处理
169172
if (columnLine.length() < 5) {
170173
continue;
@@ -174,24 +177,25 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
174177
columnLine = columnLine.replaceAll("`", " ").replaceAll("\"", " ").replaceAll("'", "").replaceAll(" ", " ").trim();
175178
//如果遇到username varchar(65) default '' not null,这种情况,判断第一个空格是否比第一个引号前
176179
try {
177-
columnName = columnLine.substring(0, columnLine.indexOf(" "));
180+
columnName = columnLine.substring(0, columnLine.indexOf(" ")).get();
178181
} catch (StringIndexOutOfBoundsException e) {
179182
System.out.println("err happened: " + columnLine);
180183
throw e;
181184
}
182185

183186
// field Name
184187
// 2019年09月08日 yj 添加是否下划线转换为驼峰的判断
188+
// 2023年8月27日 zhangfei 支持原始列名任意命名风格, 不依赖用户是否输入下划线
185189
String fieldName = null;
186190
if (ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)) {
187191
fieldName = StringUtils.lowerCaseFirst(StringUtils.underlineToCamelCase(columnName));
188192
if (fieldName.contains("_")) {
189193
fieldName = fieldName.replaceAll("_", "");
190194
}
191195
} else if (ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE.equals(nameCaseType)) {
192-
fieldName = StringUtils.lowerCaseFirst(columnName);
196+
fieldName = StringUtils.toUnderline(columnName, false);
193197
} else if (ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)) {
194-
fieldName = StringUtils.lowerCaseFirst(columnName.toUpperCase());
198+
fieldName = StringUtils.toUnderline(columnName.toUpperCase(), true);
195199
} else {
196200
fieldName = columnName;
197201
}
@@ -228,12 +232,12 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
228232
while (columnCommentMatcher.find()) {
229233
String columnCommentTmp = columnCommentMatcher.group();
230234
//System.out.println(columnCommentTmp);
231-
fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim();
235+
fieldComment = tableSql.substring(tableSql.indexOf(columnCommentTmp) + columnCommentTmp.length()).trim().get();
232236
fieldComment = fieldComment.substring(0, fieldComment.indexOf("`")).trim();
233237
}
234238
} else if (columnLine.contains(" comment")) {
235239
//20200518 zhengkai 修复包含comment关键字的问题
236-
String commentTmp = columnLine.substring(columnLine.lastIndexOf("comment") + 7).trim();
240+
String commentTmp = columnLine.substring(columnLine.lastIndexOf("comment") + 7).trim().get();
237241
// '用户ID',
238242
if (commentTmp.contains("`") || commentTmp.indexOf("`") != commentTmp.lastIndexOf("`")) {
239243
commentTmp = commentTmp.substring(commentTmp.indexOf("`") + 1, commentTmp.lastIndexOf("`"));
@@ -275,6 +279,24 @@ public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
275279
return codeJavaInfo;
276280
}
277281

282+
private static boolean isNotSpecialColumnLine(NonCaseString columnLine, int lineSeq) {
283+
return (
284+
!columnLine.containsAny(
285+
"key ",
286+
"constraint",
287+
"using",
288+
"unique ",
289+
"fulltext ",
290+
"index ",
291+
"pctincrease",
292+
"buffer_pool",
293+
"tablespace"
294+
)
295+
&& !(columnLine.contains("primary ") && columnLine.indexOf("storage") + 3 > columnLine.indexOf("("))
296+
&& !(columnLine.contains("primary ") && lineSeq > 3)
297+
);
298+
}
299+
278300
/**
279301
* 解析JSON生成类信息
280302
*

‎generator-web/src/main/resources/statics/js/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ const vm = new Vue({
3636
" 'user_name' varchar(255) NOT NULL COMMENT '用户名',\n" +
3737
" 'status' tinyint(1) NOT NULL COMMENT '状态',\n" +
3838
" 'create_time' datetime NOT NULL COMMENT '创建时间',\n" +
39+
//下面可以留着方便开发调试时打开
40+
// " `updateTime` datetime NOT NULL COMMENT '更新时间',\n" +
41+
// " ABc_under_Line-Hypen-CamelCase varchar comment '乱七八糟的命名风格',\n" +
3942
" PRIMARY KEY ('user_id')\n" +
4043
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息'",
4144
options: {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /