47 Commits

Author SHA1 Message Date
MOSHOW.K.ZHENG
271087331f default_encoding: UTF-8 2020-06-21 22:35:13 +08:00
MOSHOW.K.ZHENG
82f9ef9624 default_encoding: UTF-8 2020-06-21 21:37:46 +08:00
MOSHOW.K.ZHENG
0ed4d7ace6 修复FreemarkerUtil的Path问题导致JAR包运行时无法获取template的问题。 2020-06-21 21:29:03 +08:00
MOSHOW.K.ZHENG
83f15b4034 1.一些fix,关于封装工具类以及layui模板优化等.<br> 2.优化表备注的获取逻辑.<br> 3.生成时间格式改为yyyy-MM-dd,移除具体的时间,只保留日期 2020-05-25 21:44:46 +08:00
MOSHOW.K.ZHENG
a4f72c80dd update README.md 2020-05-24 21:17:40 +08:00
moshowgame
6c0e5764d4 新增insert-sql模式,支持对"insert into table (xxx) values (xxx)"语句进行处理,生成java代码(感谢三叔的建议) 2020-05-22 00:50:54 +08:00
moshowgame
b30ce868ff 新增mapper2(Mybatis-Annotation模板)(感谢@baisi525和@CHKEGit的建议) 2020-05-18 00:18:36 +08:00
moshowgame
e90f9f77e4 赞赏优化 2020-05-17 22:49:30 +08:00
moshowgame
e97c6c1d88 修复包含comment关键字时注释无法识别的问题。(感谢@1nchaos的反馈) 2020-05-17 22:21:33 +08:00
moshowgame
808da25d4b 新增对Jrebel配置文件的排除 - MOSHOW K ZHENG 2020-05-17 01:14:03 +08:00
moshowgame
0341e53276 代码重构!异常处理优化,Freemarker相关工具类优化,简化模板生成部分,通过template.json来配置需要生成的模板,不需要配置java文件。 2020-05-17 01:07:15 +08:00
Moshow郑锴
6149d9916d Merge pull request #83 from gaohanghang/master
1. 通过 InetAddress 类动态获取主机的ip地址 2. 折叠 catch 块
2020-05-13 19:44:40 +08:00
gaohanghang
f8b598dd89 将"项目启动启动成功"改为"项目启动成功" 2020-05-07 20:07:23 +08:00
gaohanghang
06e05abd6f 1. 通过InetAddress类动态获取主机的ip地址 2. 折叠 catch 块 2020-05-07 20:00:36 +08:00
gaohang
3316c98326 Merge pull request #8 from moshowgame/master
merge
2020-05-07 19:35:42 +08:00
MOSHOW.K.ZHENG
77748195dd 20200503:1.优化对特殊字符的处理,对于包含#和$等特殊字符的,在模板使用井和¥代替便可,escapeString方法会自动处理<br> 2.优化mybatisplus实体类相关(感谢@chunchengmeigui的反馈) 3.修优化对所有类型的判断(感谢@cnlw的反馈) 4.移除swagger-entity,该功能已经包含在‘swagger-ui’的下拉选项中 5.升级hutool和lombok版本 2020-05-03 21:08:14 +08:00
MOSHOW.K.ZHENG
0dea9b5ac0 Merge remote-tracking branch 'origin/master' 2020-05-03 19:49:20 +08:00
Moshow郑锴
3232e0f082 LICENSE
LICENSE
2020-03-15 00:40:51 +08:00
MOSHOW.K.ZHENG
45484d8949 20200306提交一套layuimini+mybatisplus的模板.修复mybatisplus一些相关问题 2020-03-06 23:16:09 +08:00
gaohang
9b6562b773 Merge pull request #7 from moshowgame/master
merge
2020-02-22 00:02:43 +08:00
Moshow郑锴
e78f38e3c9 去除mybatis模板中的方括号[]和修改模板里的类注释样式(感谢@gaohanghang的PR)
去除mybatis模板中的方括号[]和修改模板里的类注释样式(感谢@gaohanghang的PR)
2020-02-05 21:52:23 +08:00
Moshow郑锴
c94e0048ab Merge pull request #78 from gaohanghang/master
去除 mybatis 模板中的方括号[]、修改模板里的类注释样式(感谢@gaohanghang的PR)
2020-02-05 21:51:23 +08:00
MOSHOW.K.ZHENG
2316fb1780 1.新增历史记录功能,自动保存最近生成的对象 2.新增swagger开关选项和修复@Column带name参数(感谢@liuyu-struggle的建议)
1.新增历史记录功能,自动保存最近生成的对象 2.新增swagger开关选项和修复@Column带name参数(感谢@liuyu-struggle的建议)
2020-02-05 21:44:07 +08:00
gaohanghang
90750d420f 1. 去除 mybatis 模板中的方括号[],使代码更美观
2. 修改模板里的类注释样式,使注释更规范
2020-01-14 22:54:18 +08:00
gaohang
11ad5535e3 Merge pull request #6 from moshowgame/master
merge
2020-01-14 22:24:50 +08:00
MOSHOW.K.ZHENG
03152e54ef 1.修复bejson安全防护策略拦截问题(感谢@liangbintao和@1808083642的反馈) 2.优化字段名含date字符串的处理(感谢@smilexzh的反馈) 3.控制台动态输出项目访问地址(感谢@gaohanghang的提交) 2019-12-29 22:51:19 +08:00
Moshow郑锴
8b37443018 Merge pull request #73 from gaohanghang/master
动态获取tomcat启动端口,控制台打印项目访问地址(PR by @gaohanghang )
2019-12-29 22:40:20 +08:00
gaohanghang
eb7760ac18 动态获取tomcat启动端口,控制台打印项目访问地址 2019-12-27 14:43:49 +08:00
gaohang
ae7815105f Merge pull request #5 from moshowgame/master
merge
2019-11-29 20:19:56 +08:00
MOSHOW.K.ZHENG
b7861ca9fc version 2019-11-28 23:26:31 +08:00
MOSHOW.K.ZHENG
870d95e1bf version 2019-11-28 23:16:09 +08:00
MOSHOW.K.ZHENG
a84a4c1087 1.修复支持string-copy导致的以n结尾的字母不显示问题 2.jpa-entity新增swagger@ApiModel@ApiModelProperty注解和SQL字段@Column注解(感谢@yjq907的建议) 2019-11-28 22:19:53 +08:00
Moshow郑锴
f746461188 Merge pull request #60 from gaohanghang/master
更新实体类模板,将 serialVersionUID 所在行的代码换行,使代码更加美观
2019-11-26 23:06:14 +08:00
MOSHOW.K.ZHENG
02c43a8a9e Update README.md 2019-11-26 22:58:24 +08:00
MOSHOW.K.ZHENG
f45b1bfa8a add release jar download url&img
add release jar download url&img
2019-11-26 22:56:20 +08:00
MOSHOW.K.ZHENG
a68989be66 1.springboot2内置tomcat更换为性能更强大的undertow 2.修复tinyintTransType参数丢失问题
1.springboot2内置tomcat更换为性能更强大的undertow 2.修复tinyintTransType参数丢失问题
2019-11-26 22:45:23 +08:00
MOSHOW.K.ZHENG
65b0584c45 Update index.ftl
修复缺失的字段
2019-11-26 21:56:46 +08:00
gaohanghang
6cfa5d2c63 更新实体类模板,将 serialVersionUID 所在行的代码换行,使代码更加美观 2019-11-25 02:16:36 +08:00
gaohang
a4736f65b5 Merge pull request #4 from moshowgame/master
merge
2019-11-25 01:51:01 +08:00
Moshow郑锴
72257e00bd Merge pull request #59 from moshowgame/201911dev
Merge from 201911dev
2019-11-24 12:10:58 +08:00
MOSHOW.K.ZHENG
1bb8881928 Update
4.新增对复制String代码中的乱SQL代码的支持 5.优化对JSON的父子节点/处理,JSONObject和JSONArray节点处理,子节点缺失'{'头处理
2019-11-24 12:08:24 +08:00
MOSHOW.K.ZHENG
dae662836b Update
1.java代码结构优化. 2.新增简单的json生成模式 3.新增简单的正则表达式匹配模式(感谢@ydq的贡献)
2019-11-24 10:25:06 +08:00
Moshow郑锴
d738c587c6 Update README.md
update to real markdown
2019-11-23 13:55:56 +08:00
MOSHOW.K.ZHENG
04b9294450 donate优化 2019-11-23 10:24:10 +08:00
MOSHOW.K.ZHENG
17707d68e8 donate优化 2019-11-23 10:23:31 +08:00
MOSHOW.K.ZHENG
1b5d79ded1 1.移除频繁出错和被过滤的layer,改为jquery-toast. 2.Util功能优化,新增json和xml. 2019-11-23 10:10:26 +08:00
gaohang
60b214bf0f Merge pull request #3 from moshowgame/master
merge
2019-11-15 00:04:39 +08:00
55 changed files with 2222 additions and 1277 deletions

3
.gitignore vendored
View File

@@ -198,4 +198,7 @@ buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
#rebel
rebel.xml
rebel-remote.xml
# End of https://www.gitignore.io/api/java,maven,eclipse,java-web,intellij+all

21
LICENSE.txt Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Moshow K ZHENG(Moshow/郑锴/大狼狗)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

168
README.md
View File

@@ -1,67 +1,101 @@
![image](https://img.shields.io/badge/SpringBoot2-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-brightgreen.svg)
![image](https://img.shields.io/badge/Freemarker-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-brightgreen.svg)
![image](https://img.shields.io/badge/CodeGenerator-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-brightgreen.svg)
[![Build Status](https://travis-ci.org/moshowgame/SpringBootCodeGenerator.svg?branch=master)](https://travis-ci.org/moshowgame/SpringBootCodeGenerator)
<br>
SpringBootCodeGenerator
----
基于SpringBoot2+Freemarker的代码生成器√以释放双手为目的√支持mysql/oracle/pgsql三大数据库<br>
√用DDL-SQL语句生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL相关代码.<br><br>
另外感谢bejson三叔将他部署在 http://java.bejson.com/generator 上目前是besjon专供工具(线上版本不一定是最新的,会有延迟,请谅解,谢谢).
<br><br>
<table><tbody>
<tr><td>访问路径</td> <td>http://127.0.0.1:1234/generator</td></tr>
<tr><td>在线地址</td> <td>http://java.bejson.com/generator</td></tr>
<tr><td>CSDN博客</td> <td>http://zhengkai.blog.csdn.net</td></tr>
<tr><td></td> <td></td></tr>
<tr><td>更新日期</td> <td>更新内容</td></tr>
<tr><td>20191116<td>优化对primary关键字的处理(感谢@liujiansgit的反馈). </td></tr>
<tr><td>20191115<td>1.添加tinyint类型转换(感谢@lixiliang&@liujiansgit的Suggestion) 2.添加一键复制功能(感谢@gaohanghang的Suggestion) 3.Mybatis的insert增加keyProperty="id"用于返回自增id(感谢@88888888888888888888的Suggestion) 4.优化date类型的支持(感谢@SteveLsf的反馈) 5.其他一些优化. </td></tr>
<tr><td>20191015<td>修复jdbcTemplates中insert语句第一个字段丢失的问题. </td></tr>
<tr><td>20190915<td>1.添加对象getset模板 2.添加sql模板 3.启动类添加日志输出,方便项目使用(感谢@gaohanghang 的pull request) </td></tr>
<tr><td>20190910-2<td>优化以及更新Maven依赖减少打包体积. </td></tr>
<tr><td>20190910-1<td>1.修复mapper接口load方法但是xml中方法不匹配问题 2.移除mapper中CRUD时的@param 注解会影响xml的解析(感谢@caojiantao的反馈).3.优化MyBatis的xml文件对Oracle的支持.(感谢@wylove1992的反馈) 4.新增对boolean的处理(感谢@violinxsc的反馈)以及优化tinyint类型生成boolean类型问题(感谢@hahaYhui的反馈) </td></tr>
<tr><td>20190909<td>添加是否下划线转换为驼峰的选择(感谢@youngking28 的pull request).</td></tr>
<tr><td>20190518<td>1.优化注释 2.修改 mybatis模板中 controller注解 3.修改 mybatis模板中 dao文件使用为 mapper文件 4.修改 mybatis模板中 service实现类中的一个 bug 5.修改 index.ftl文件中 mybatis模板的 dao -> mapper(感谢@unqin的pull request)</td></tr>
<tr><td>20190511<td>优化mybatis模块的dao和xml模板修改dao接口注解为@Repository所有dao参数改为包装类删除update语句最后的UpdateTime = NOW()修改dao接口文件的方法注释使其更符合javaDoc的标准修改insert语句增加插入行主键的返回修改load的方法名为selectByPrimaryKey修改xml的update语句新增动态if判空修改xml的insert语句新增动态插入判空更符合mybatisGenerator标准(感谢@Archer-Wen的贡献 ).</td></tr>
<tr><td>20190429<td>新增返回封装工具类设置优化对oracle注释comment on column的支持(感谢@liukex反馈)优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 ).</td></tr>
<tr><td>20190211<td>提交gitignore解决StringUtils.lowerCaseFirst潜在的NPE异常校验修改为@RequestParam参数校验lombok之@Data和@Slf4j优化fix JdbcDAO模板类名显示为中文问题WebMvcConfig整合MessageConverter模板代码分类(感谢@liutf和@tfgzs的pull request).</td></tr>
<tr><td>20190210<td>实体生成规则切换为包装类型,不再采用基本数据类型,为实体类生成添加显示的默认构造方法(感谢@h2so的pull request).</td></tr>
<tr><td>20190106<td>修复处理number/decimal(x,x)类型的逻辑(感谢@arthaschan的反馈)修复JdbcTemplates模板两处错误(感谢@everflourish的反馈).</td></tr>
<tr><td>20181212<td>首页UI优化新增MybatisPlus模块(感谢@三叔同事的建议),修复作者名和包名获取失败问题(感谢@Yanch1994的反馈).</td></tr>
<tr><td>20181122<td>优化正则表达式点号的处理优化处理字段类型对number类型增加intlongBigDecimal的区分判断(感谢@lshz0088的指导).</td></tr>
<tr><td>20181108<td>修复非字段描述"KEY FK_xxxx (xxxx)"导致生成KEY字段情况(感谢@tornadoorz反馈).</td></tr>
<tr><td>20181018<td>支持double(x,x)的类型以及comment里面包含一些特殊字符的处理(感谢@tanwubo的反馈).</td></tr>
<tr><td>20181010<td>CDN变更修复CDN不稳定导致网页js报错问题.</td></tr>
<tr><td>20181003<td>新增element-ui/bootstrap生成.</td></tr>
<tr><td>20181002<td>修复公共CDN之Layer.js404问题导致项目无法生成.</td></tr>
<tr><td>20180927<td>优化COMMENT提取逻辑支持多种复杂情况的注释(感谢@raodeming的反馈).</td></tr>
<tr><td>20180926<td>全新BeetlSQL模块以及一些小细节优化(感谢@三叔同事的建议).</td></tr>
<tr><td>20180925<td>优化SQL表和字段备注的推断包括pgsql/oralce的comment on column/table情况处理等.</td></tr>
<tr><td>20180918<td>优化SQL类型推断.优化PrimaryKey判断.修复jpacontroller中Repository拼写错误问题.</td></tr>
<tr><td>20180917<td>全新首页静态文件全部采用CDN.新增jdbcTemplate模块.</td></tr>
<tr><td>20180916-2<td>优化oracle支持优化DDL语句中"或者'或者空格的支持.</td></tr>
<tr><td>20180916-1<td>补充char/clob/blob/json等类型如果类型未知默认为String.</td></tr>
<tr><td>20180915<td>新增Swagger-UI模板.修复一些命名和导入问题.JPA的Entity默认第一个字段为Id如果不是请手工修改.</td></tr>
<tr><td>20180913<td>修复字段没有描述以及类型为DATE型导致的问题.新增JPA的Controller模板.</td></tr>
<tr><td>20180831<td>初始化项目.新增JPA系列Entity+Repository模板.</td></tr>
</tbody></table>
<table><tbody>
<tr><td>字段名</td> <td>说明</td></tr>
<tr><td>packageName</td> <td>自定义的包名</td></tr>
<tr><td>authorName</td> <td>自定义的作者名</td></tr>
<tr><td>returnUtil</td> <td>自定义的返回Util</td></tr>
<tr><td>tableName</td> <td>sql中的表名</td></tr>
<tr><td>className</td> <td>java类名</td></tr>
<tr><td>classComment</td> <td>sql表备注/java类备注</td></tr>
<tr><td>fieldName</td> <td>字段名</td></tr>
<tr><td>fieldComment</td> <td>字段备注</td></tr>
</tbody></table>
<img src="./codegenerator1.png">
<img src="./codegenerator2.png">
<img src="./codegenerator3.png">
<img src="./donate.jpg">
# SpringBootCodeGenerator
![image](https://img.shields.io/badge/SpringBoot2-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-blue.svg)
![image](https://img.shields.io/badge/Freemarker-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-blue.svg)
![image](https://img.shields.io/badge/CodeGenerator-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%85-blue.svg)
[![Build Status](https://travis-ci.org/moshowgame/SpringBootCodeGenerator.svg?branch=master)](https://travis-ci.org/moshowgame/SpringBootCodeGenerator)
# Description
-基于SpringBoot2+Freemarker+Bootstrap
- √ 以解放双手为目的减少大量重复的CRUD工作
- √ 支持mysql/oracle/pgsql三大数据库
- √ 用DDL-SQL语句生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL相关代码.
# Advantage
- 支持DDL SQL/INSERT SQL/SIMPLE JSON生成模式
- 自动记忆最近生成的内容最多保留9个
- 提供众多通用模板易于使用复制粘贴加简单修改即可完成CRUD操作
- 支持特殊字符模板(`#`请用`井`代替;`$`请用`¥`代替)
- 根据comment=(mysql)或者comment on table(pgsql/oracle)生成类名注释
# Url
|访问路径|http://localhost:1234/generator|
|----|----|
|在线地址|http://java.bejson.com/generator|
|CSDN博客|http://zhengkai.blog.csdn.net|
|最新Jar包|https://github.com/moshowgame/SpringBootCodeGenerator/releases|
感谢bejson三叔将他部署在[BEJSON](www.bejson.com)上目前是besjon专供的金牌工具(线上版本不一定是最新的,会有延迟,请谅解,谢谢).
# Update
|更新日期|更新内容|
|----|----|
|20200621|修复FreemarkerUtil的Path问题导致JAR包运行时无法获取template的问题。|
|20200525|1.一些fix,关于封装工具类以及layui模板优化等.<br> 2.优化表备注的获取逻辑.<br> 3.生成时间格式改为yyyy-MM-dd,移除具体的时间,只保留日期|
|20200522|1.新增insert-sql模式,支持对"insert into table (xxx) values (xxx)"语句进行处理,生成java代码(感谢三叔的建议).|
|20200517|1.代码重构!异常处理优化,Freemarker相关工具类优化,简化模板生成部分,通过template.json来配置需要生成的模板,不需要配置java文件.<br> 2.修复包含comment关键字时注释无法识别的问题.(感谢@1nchaos的反馈).<br> 3.赞赏优化,感谢大家的赞赏.<br> 4.新增mapper2(Mybatis-Annotation模板)(感谢@baisi525和@CHKEGit的建议).|
|20200503|1.优化对特殊字符的处理,对于包含#和$等特殊字符的,在模板使用井和¥代替便可,escapeString方法会自动处理.<br> 2.优化mybatisplus实体类相关(感谢@chunchengmeigui的反馈).<br> 3.修优化对所有类型的判断(感谢@cnlw的反馈).<br> 4.移除swagger-entity,该功能已经包含在swagger-ui的下拉选项中 <br> 5.升级hutool和lombok版本|
|20200306|1.提交一套layuimini+mybatisplus的模板.<br> 2.修复mybatisplus一些相关问题. |
|20200206|1.新增历史记录功能,自动保存最近生成的对象.<br> 2.新增swagger开关选项和修复@Column带name参数(感谢@liuyu-struggle的建议).<br> 3.去除mybatis模板中的方括号[]和修改模板里的类注释样式(感谢@gaohanghang的PR)|
|20191229|1.修复bejson安全防护策略拦截问题(感谢@liangbintao和@1808083642的反馈).<br> 2.优化字段名含date字符串的处理(感谢@smilexzh的反馈).<br> 3.控制台动态输出项目访问地址(感谢@gaohanghang的提交)|
|20191128|1.修复支持string-copy导致的以n结尾的字母不显示问题.<br> 2.jpa-entity新增swagger@ApiModel@ApiModelProperty注解和SQL字段@Column注解(感谢@yjq907的建议) |
|20191126|1.springboot2内置tomcat更换为性能更强大的undertow.<br> 2.修复tinyintTransType参数丢失问题 |
|20191124|1.java代码结构优化.<br> 2.新增简单的json生成模式.<br> 3.新增简单的正则表达式匹配模式(感谢@ydq的贡献).<br> 4.新增对复制String代码中的乱SQL代码的支持 5.优化对JSON的父子节点/处理,JSONObject和JSONArray节点处理,子节点缺失'{'头处理|
|20191123|1.移除频繁出错和被过滤的layer,改为jquery-toast.<br> 2.Util功能优化,新增json和xml.|
|20191116|优化对primary关键字的处理(感谢@liujiansgit的反馈). |
|20191115|1.添加tinyint类型转换(感谢@lixiliang&@liujiansgit的Suggestion).<br> 2.添加一键复制功能(感谢@gaohanghang的Suggestion).<br> 3.Mybatis的insert增加keyProperty="id"用于返回自增id(感谢@88888888888888888888的Suggestion).<br> 4.优化date类型的支持(感谢@SteveLsf的反馈).<br> 5.其他一些优化. |
|20191015|修复jdbcTemplates中insert语句第一个字段丢失的问题. |
|20190915|1.添加对象getset模板.<br> 2.添加sql模板.<br> 3.启动类添加日志输出,方便项目使用(感谢@gaohanghang 的pull request) |
|20190910|优化以及更新Maven依赖,减少打包体积.<br> 1.修复mapper接口load方法,但是xml中方法不匹配问题.<br> 2.移除mapper中CRUD时的@param 注解,会影响xml的解析(感谢@caojiantao的反馈).<br> 3.优化MyBatis的xml文件对Oracle的支持.(感谢@wylove1992的反馈).<br> 4.新增对boolean的处理(感谢@violinxsc的反馈)以及优化tinyint类型生成boolean类型问题(感谢@hahaYhui的反馈) |
|20190909|添加是否下划线转换为驼峰的选择(感谢@youngking28 的pull request).|
|20190518|1.优化注释.<br> 2.修改 mybatis模板中 controller注解.<br> 3.修改 mybatis模板中 dao文件使用为 mapper文件.<br> 4.修改 mybatis模板中 service实现类中的一个 bug.<br> 5.修改 index.ftl文件中 mybatis模板的 dao -> mapper(感谢@unqin的pull request)|
|20190511|优化mybatis模块的dao和xml模板,修改dao接口注解为@Repository,所有dao参数改为包装类,删除update语句最后的UpdateTime = NOW(),修改dao接口文件的方法注释使其更符合javaDoc的标准,修改insert语句增加插入行主键的返回,修改load的方法名为selectByPrimaryKey,修改xml的update语句新增动态if判空,修改xml的insert语句新增动态插入判空,更符合mybatisGenerator标准(感谢@Archer-Wen的贡献 ).|
|20190429|新增返回封装工具类设置.<br> 优化对oracle注释comment on column的支持(感谢@liukex反馈).<br> 优化对普通和特殊storage关键字的判断(感谢@AhHeadFloating的反馈 ).|
|20190211|提交gitignore,解决StringUtils.lowerCaseFirst潜在的NPE异常,校验修改为@RequestParam参数校验,lombok之@Data和@Slf4j优化,fix JdbcDAO模板类名显示为中文问题,WebMvcConfig整合MessageConverter,模板代码分类(感谢@liutf和@tfgzs的pull request).|
|20190210|实体生成规则切换为包装类型,不再采用基本数据类型,为实体类生成添加显示的默认构造方法(感谢@h2so的pull request).|
|20190106|修复处理number/decimal(x,x)类型的逻辑(感谢@arthaschan的反馈).<br> 修复JdbcTemplates模板两处错误(感谢@everflourish的反馈).|
|20181212|首页UI优化.<br> 新增MybatisPlus模块(感谢@三叔同事的建议).<br> 修复作者名和包名获取失败问题(感谢@Yanch1994的反馈).|
|20181122|优化正则表达式点号的处理,优化处理字段类型,对number类型增加int,long,BigDecimal的区分判断(感谢@lshz0088的指导).|
|20181108|修复非字段描述"KEY FK_xxxx (xxxx)"导致生成KEY字段情况(感谢@tornadoorz反馈).|
|20181018|支持double(x,x)的类型,以及comment里面包含一些特殊字符的处理(感谢@tanwubo的反馈).|
|20181010|CDN变更,修复CDN不稳定导致网页js报错问题.|
|20181003|新增element-ui/bootstrap生成.|
|20181002|修复公共CDN之Layer.js404问题,导致项目无法生成.|
|20180927|优化COMMENT提取逻辑,支持多种复杂情况的注释(感谢@raodeming的反馈).|
|20180926|全新BeetlSQL模块,以及一些小细节优化(感谢@三叔同事的建议).|
|20180925|优化SQL表和字段备注的推断,包括pgsql/oralce的comment on column/table情况处理等.|
|20180918|优化SQL类型推断.<br> 优化PrimaryKey判断.<br> 修复jpacontroller中Repository拼写错误问题.|
|20180917|全新首页,静态文件全部采用CDN.新增jdbcTemplate模块.|
|20180916|1.优化oracle支持,优化DDL语句中"或者'或者空格的支持.<br> 2.补充char/clob/blob/json等类型,如果类型未知,默认为String.|
|20180915|新增Swagger-UI模板.修复一些命名和导入问题.JPA的Entity默认第一个字段为Id,如果不是请手工修改.|
|20180913|修复字段没有描述以及类型为DATE型导致的问题.新增JPA的Controller模板.|
|20180831|初始化项目.新增JPA系列Entity+Repository模板.|
# ClassInfo/TableInfo
|字段名|说明|
|-|-|
|packageName|自定义的包名|
|authorName|自定义的作者名|
|returnUtil|自定义的返回Util|
|tableName|sql中的表名|
|className|java类名|
|classComment|sql表备注/java类备注|
|fieldName|字段名|
|fieldComment|字段备注|
# how to add a new template
1. code-generator中找到对应分类新增一个.ftl文件
2. 根据类信息编写freemarker模板.ftl文件
3. 修改template.json文件新增模板信息
4. index页面增加一个button
5. reload,test,complete
<img src="./codegenerator1.png">
<img src="./codegenerator2.png">
<img src="./codegenerator3.png">
<img src="./codegenerator4.png">
<img src="./donate.png">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 121 KiB

BIN
codegenerator4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

BIN
donate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

View File

@@ -7,12 +7,12 @@
<parent>
<groupId>com.softdev.system</groupId>
<artifactId>SpringBootCodeGenerator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>2.0</version>
</parent>
<groupId>com.softdev.system</groupId>
<artifactId>generator-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>2.0</version>
<packaging>jar</packaging>
<properties>
@@ -38,10 +38,10 @@
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>-->
<dependency>
<!--<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependency>-->
</dependencies>
@@ -65,7 +65,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<version>3.8.1</version>
<configuration>
<skip>true</skip>
<compilerId>javac</compilerId>
@@ -87,25 +87,24 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<configuration>
<!--<failOnMissingWebXml>false</failOnMissingWebXml>-->
<includeEmptyDirs>true</includeEmptyDirs>
</configuration>
</plugin>
<plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<version>3.2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warSourceExcludes>upload/**</warSourceExcludes>
</configuration>
</plugin>
</plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.4.RELEASE</version>
<executions>
<execution>
<goals>

View File

@@ -5,10 +5,8 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@Slf4j
public class GeneratorWebApplication {
public static void main(String[] args) {
SpringApplication.run(GeneratorWebApplication.class,args);
log.info("项目启动启动成功!访问地址: http://localhost:1234/generator");
}
}

View File

@@ -1,23 +1,20 @@
package com.softdev.system.generator.config;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.softdev.system.generator.util.ApiReturnObject;
import com.softdev.system.generator.util.ApiReturnUtil;
@ControllerAdvice
public class GlobalDefaultExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiReturnObject defaultExceptionHandler(HttpServletRequest req,Exception e) {
e.printStackTrace();
//return new ApiReturnObject("01","server error", e.getMessage());
return ApiReturnUtil.error("服务器异常",e.getMessage());
}
}
package com.softdev.system.generator.config;
import com.softdev.system.generator.entity.ReturnT;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
public class GlobalDefaultExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ReturnT defaultExceptionHandler(HttpServletRequest req,Exception e) {
e.printStackTrace();
return ReturnT.ERROR(e.getMessage());
}
}

View File

@@ -0,0 +1,36 @@
package com.softdev.system.generator.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @Description 通过实现ApplicationListener接口动态获取tomcat启动端口和访问路径通过InetAddress类获取主机的ip地址最后控制台打印项目访问地址
* @Author Gao Hang Hang
* @Date 2019-12-27 14:37
**/
@Component
@Slf4j
public class ServerConfig implements ApplicationListener<WebServerInitializedEvent> {
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
try {
InetAddress inetAddress = Inet4Address.getLocalHost();
// 主机ip地址
String hostAddress = inetAddress.getHostAddress();
// tomcat启动端口
int serverPort = event.getWebServer().getPort();
// 新增动态path by zhengkai
String serverPath = event.getApplicationContext().getApplicationName();
log.info("项目启动成功!访问地址: http://{}:{}{}", hostAddress, serverPort, serverPath);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}

View File

@@ -1,49 +1,49 @@
package com.softdev.system.generator.config;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* 2019-2-11 liutf WebMvcConfig 整合 cors 和 SpringMvc MessageConverter
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/* @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("x-requested-with")
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE")
.maxAge(3600);
}*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//FastJsonHttpMessageConverter
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setCharset(Charset.forName("UTF-8"));
fastConverter.setFastJsonConfig(fastJsonConfig);
//StringHttpMessageConverter
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setDefaultCharset(Charset.forName("UTF-8"));
stringConverter.setSupportedMediaTypes(fastMediaTypes);
converters.add(stringConverter);
converters.add(fastConverter);
}
package com.softdev.system.generator.config;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* 2019-2-11 liutf WebMvcConfig 整合 cors 和 SpringMvc MessageConverter
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/* @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("x-requested-with")
.allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE")
.maxAge(3600);
}*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//FastJsonHttpMessageConverter
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setCharset(StandardCharsets.UTF_8);
fastConverter.setFastJsonConfig(fastJsonConfig);
//StringHttpMessageConverter
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setDefaultCharset(StandardCharsets.UTF_8);
stringConverter.setSupportedMediaTypes(fastMediaTypes);
converters.add(stringConverter);
converters.add(fastConverter);
}
}

View File

@@ -1,19 +1,18 @@
package com.softdev.system.generator.controller;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.ParamInfo;
import com.softdev.system.generator.entity.ReturnT;
import com.softdev.system.generator.util.FreemarkerTool;
import com.softdev.system.generator.service.GeneratorService;
import com.softdev.system.generator.util.TableParseUtil;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -26,94 +25,50 @@ import java.util.Map;
public class IndexController {
@Autowired
private FreemarkerTool freemarkerTool;
private GeneratorService generatorService;
@RequestMapping("/")
@GetMapping("/")
public String index() {
return "index";
}
@RequestMapping("/genCode")
@PostMapping("/genCode")
@ResponseBody
public ReturnT<Map<String, String>> codeGenerate(String tableSql,
//2019-2-10 liutf 修改为@RequestParam参数校验
@RequestParam(required = false, defaultValue = "大狼狗") String authorName,
@RequestParam(required = false, defaultValue = "com.softdev.system")String packageName,
@RequestParam(required = false, defaultValue = "ApiReturnUtil")String returnUtil,
@RequestParam(required = false, defaultValue = "true")boolean isUnderLineToCamelCase,
@RequestParam(required = false, defaultValue = "boolean")String tinyintTransType
) {
public ReturnT codeGenerate(@RequestBody ParamInfo paramInfo ) throws Exception {
try {
if (StringUtils.isBlank(tableSql)) {
return new ReturnT<>(ReturnT.FAIL_CODE, "表结构信息不可为空");
}
// parse table
ClassInfo classInfo = TableParseUtil.processTableIntoClassInfo(tableSql, isUnderLineToCamelCase, tinyintTransType);
// code genarete
Map<String, Object> params = new HashMap<String, Object>(8);
params.put("classInfo", classInfo);
params.put("authorName", authorName);
params.put("packageName", packageName);
params.put("returnUtil", returnUtil);
// result
Map<String, String> result = new HashMap<String, String>(32);
//UI
result.put("swagger-ui", freemarkerTool.processString("code-generator/ui/swagger-ui.ftl", params));
result.put("element-ui", freemarkerTool.processString("code-generator/ui/element-ui.ftl", params));
result.put("bootstrap-ui", freemarkerTool.processString("code-generator/ui/bootstrap-ui.ftl", params));
//mybatis old
result.put("controller", freemarkerTool.processString("code-generator/mybatis/controller.ftl", params));
result.put("service", freemarkerTool.processString("code-generator/mybatis/service.ftl", params));
result.put("service_impl", freemarkerTool.processString("code-generator/mybatis/service_impl.ftl", params));
result.put("mapper", freemarkerTool.processString("code-generator/mybatis/mapper.ftl", params));
result.put("mybatis", freemarkerTool.processString("code-generator/mybatis/mybatis.ftl", params));
result.put("model", freemarkerTool.processString("code-generator/mybatis/model.ftl", params));
//jpa
result.put("entity", freemarkerTool.processString("code-generator/jpa/entity.ftl", params));
result.put("repository", freemarkerTool.processString("code-generator/jpa/repository.ftl", params));
result.put("jpacontroller", freemarkerTool.processString("code-generator/jpa/jpacontroller.ftl", params));
//jdbc template
result.put("jtdao", freemarkerTool.processString("code-generator/jdbc-template/jtdao.ftl", params));
result.put("jtdaoimpl", freemarkerTool.processString("code-generator/jdbc-template/jtdaoimpl.ftl", params));
//beetsql
result.put("beetlmd", freemarkerTool.processString("code-generator/beetlsql/beetlmd.ftl", params));
result.put("beetlentity", freemarkerTool.processString("code-generator/beetlsql/beetlentity.ftl", params));
result.put("beetlentitydto", freemarkerTool.processString("code-generator/beetlsql/beetlentitydto.ftl", params));
result.put("beetlcontroller", freemarkerTool.processString("code-generator/beetlsql/beetlcontroller.ftl", params));
//mybatis plus
result.put("pluscontroller", freemarkerTool.processString("code-generator/mybatis-plus/pluscontroller.ftl", params));
result.put("plusmapper", freemarkerTool.processString("code-generator/mybatis-plus/plusmapper.ftl", params));
//util
result.put("util", freemarkerTool.processString("code-generator/util/util.ftl", params));
//sql generate
result.put("select", freemarkerTool.processString("code-generator/sql/select.ftl", params));
result.put("insert", freemarkerTool.processString("code-generator/sql/insert.ftl", params));
result.put("update", freemarkerTool.processString("code-generator/sql/update.ftl", params));
result.put("delete", freemarkerTool.processString("code-generator/sql/delete.ftl", params));
// 计算,生成代码行数
int lineNum = 0;
for (Map.Entry<String, String> item: result.entrySet()) {
if (item.getValue() != null) {
lineNum += StringUtils.countMatches(item.getValue(), "\n");
}
}
log.info("生成代码行数:{}", lineNum);
//测试环境可自行开启
//log.info("生成代码数据:{}", result);
return new ReturnT<>(result);
} catch (IOException | TemplateException e) {
log.error(e.getMessage(), e);
return new ReturnT<>(ReturnT.FAIL_CODE, "表结构解析失败"+e.getMessage());
if (paramInfo.getTableSql().trim().length()<1) {
return ReturnT.ERROR("表结构信息不可为空");
}
//1.Parse Table Structure 表结构解析
ClassInfo classInfo = null;
switch (paramInfo.getDataType()){
//JSON模式parse field from json string
case "json":classInfo = TableParseUtil.processJsonToClassInfo(paramInfo);break;
//INSERT SQL模式parse field from insert sql
case "insert-sql":classInfo = TableParseUtil.processInsertSqlToClassInfo(paramInfo);break;
//正则表达式模式非完善版本parse sql by regex
case "sql-regex":classInfo = TableParseUtil.processTableToClassInfoByRegex(paramInfo);break;
//默认模式default parse sql by java
default : classInfo = TableParseUtil.processTableIntoClassInfo(paramInfo);break;
}
//2.Set the params 设置表格参数
Map<String, Object> params = new HashMap<String, Object>(8);
params.put("classInfo", classInfo);
params.put("tableName", classInfo==null?System.currentTimeMillis():classInfo.getTableName());
params.put("authorName", paramInfo.getAuthorName());
params.put("packageName", paramInfo.getPackageName());
params.put("returnUtil", paramInfo.getReturnUtil());
params.put("swagger", paramInfo.isSwagger());
//log the generated table and filed size记录解析了什么表有多少个字段
log.info("generated table:" + classInfo.getTableName() + ",field size:" + (classInfo.getFieldList() == null ? "" : classInfo.getFieldList().size()));
//3.generate the code by freemarker template and param . Freemarker根据参数和模板生成代码
Map<String, String> result = generatorService.getResultByParams(params);
return ReturnT.SUCCESS(result);
}
}

View File

@@ -0,0 +1,26 @@
package com.softdev.system.generator.entity;
import lombok.Data;
/**
* Post data - ParamInfo
* @author zhengkai.blog.csdn.net
*/
@Data
public class ParamInfo {
private String tableSql;
private String authorName;
private String packageName;
private String returnUtil;
private String nameCaseType;
private String tinyintTransType;
private String dataType;
private boolean swagger;
@Data
public static class NAME_CASE_TYPE{
public static String CAMEL_CASE="CamelCase";
public static String UNDER_SCORE_CASE="UnderScoreCase";
public static String UPPER_UNDER_SCORE_CASE="UpperUnderScoreCase";
}
}

View File

@@ -5,29 +5,61 @@ import lombok.Data;
import java.io.Serializable;
/**
* common return
* @author xuxueli 2015-12-4 16:32:31
* common returnT:公共返回封装类
* @author zhengkai.blog.csdn.net
*/
@Data
public class ReturnT<T> implements Serializable {
public class ReturnT implements Serializable {
public static final long serialVersionUID = 42L;
public static final int SUCCESS_CODE = 200;
public static final int FAIL_CODE = 500;
public static final ReturnT<String> SUCCESS = new ReturnT<>(null);
public static final ReturnT<String> FAIL = new ReturnT<>(FAIL_CODE, null);
public static final int PAGE_CODE = 0;
public static final String OBJECT_NOT_FOUND = "找不到该对象";
public static final String OPERATION_SUCCESS = "操作成功";
private int code;
private String msg;
private T data;
private Object data;
private int count;
public ReturnT(int code, String msg) {
this.code = code;
this.msg = msg;
}
public ReturnT(T data) {
public ReturnT(int code, String msg,Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public ReturnT(Object data) {
this.code = SUCCESS_CODE;
this.data = data;
}
public ReturnT( Object data , int count ) {
this.code = PAGE_CODE;
this.data = data;
this.count = count;
}
public static ReturnT PAGE( Object data , int count){
return new ReturnT(data,count);
}
public static ReturnT PAGE( Object data , long count){
return new ReturnT(data,Integer.parseInt(count+""));
}
public static ReturnT SUCCESS(){
return new ReturnT(SUCCESS_CODE,OPERATION_SUCCESS);
}
public static ReturnT SUCCESS(String msg){
return new ReturnT(SUCCESS_CODE,msg);
}
public static ReturnT SUCCESS(Object data){
return new ReturnT(data);
}
public static ReturnT ERROR(String msg){
return new ReturnT(FAIL_CODE,msg);
}
public static ReturnT ERROR(){
return new ReturnT(FAIL_CODE,OBJECT_NOT_FOUND);
}
}

View File

@@ -0,0 +1,18 @@
package com.softdev.system.generator.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class TemplateConfig implements Serializable {
public static final long serialVersionUID = 66L;
Integer id;
String name;
String group;
String path;
String description;
}

View File

@@ -0,0 +1,17 @@
package com.softdev.system.generator.service;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Map;
/**
* GeneratorService
* @author zhengkai.blog.csdn.net
*/
public interface GeneratorService {
public Map<String,String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException;
}

View File

@@ -0,0 +1,62 @@
package com.softdev.system.generator.service;
import com.alibaba.fastjson.JSON;
import com.softdev.system.generator.entity.TemplateConfig;
import com.softdev.system.generator.util.FreemarkerUtil;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* GeneratorService
* @author zhengkai.blog.csdn.net
*/
@Slf4j
@Service
public class GeneratorServiceImpl implements GeneratorService {
@Autowired
private FreemarkerUtil freemarkerTool;
String templateCpnfig=null;
/**
* 从项目中的JSON文件读取String
* @author zhengkai.blog.csdn.net
*/
public String getTemplateConfig() throws IOException {
templateCpnfig=null;
if(templateCpnfig!=null){
}else{
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template.json");
templateCpnfig = new BufferedReader(new InputStreamReader(inputStream))
.lines().collect(Collectors.joining(System.lineSeparator()));
inputStream.close();
}
//log.info(JSON.toJSONString(templateCpnfig));
return templateCpnfig;
}
/**
* 根据配置的Template模板进行遍历解析得到生成好的String
* @author zhengkai.blog.csdn.net
*/
@Override
public Map<String, String> getResultByParams(Map<String, Object> params) throws IOException, TemplateException {
Map<String, String> result = new LinkedHashMap<>(32);
result.put("tableName",params.get("tableName")+"");
List<TemplateConfig> templateConfigList = JSON.parseArray(getTemplateConfig(),TemplateConfig.class);
for (TemplateConfig item:templateConfigList){
result.put(item.getName(), freemarkerTool.processString(item.getGroup()+"/"+item.getName()+".ftl", params));
}
return result;
}
}

View File

@@ -1,42 +0,0 @@
package com.softdev.system.generator.util;
import lombok.Data;
import java.io.Serializable;
@Data
public class ApiReturnObject implements Serializable{
private static final long serialVersionUID = 1L;
public ApiReturnObject(String errorCode, Object errorMessage, Object returnObject) {
super();
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.returnObject = returnObject;
}
public ApiReturnObject(Object errorMessage, Object returnObject) {
super();
this.errorMessage = errorMessage;
this.returnObject = returnObject;
}
String errorCode="00";
Object errorMessage;
Object returnObject;
String pageNumber;
String pageSize;
String totalElements;
String totalPages;
public ApiReturnObject(String pageNumber,String pageSize,String totalElements,String totalPages,String errorCode, Object errorMessage, Object returnObject) {
super();
this.pageNumber = pageNumber;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.returnObject = returnObject;
this.pageSize = pageSize;
this.totalElements = totalElements;
this.totalPages = totalPages;
}
}

View File

@@ -1,50 +0,0 @@
package com.softdev.system.generator.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class ApiReturnUtil implements Serializable{
private static final long serialVersionUID = 1L;
public static ApiReturnObject error(Object errorMessage) {
System.out.println(errorMessage);
List<Object> object=new ArrayList<Object>();
return new ApiReturnObject("01",errorMessage,object);
}
public static ApiReturnObject error(Object errorMessage, Object returnObject) {
List<Object> object=new ArrayList<Object>();
object.add(returnObject);
return new ApiReturnObject("01",errorMessage,object);
}
public static ApiReturnObject success(Object returnObject) {
if(returnObject instanceof java.util.List){
return new ApiReturnObject("00","success",returnObject);
}else {
List<Object> object=new ArrayList<Object>();
object.add(returnObject);
return new ApiReturnObject("00","success",object);
}
}
public static ApiReturnObject success(Object errorMessage, Object returnObject) {
if(returnObject instanceof java.util.List){
return new ApiReturnObject("00",errorMessage,returnObject);
}else {
List<Object> object=new ArrayList<Object>();
object.add(returnObject);
return new ApiReturnObject("00",errorMessage,object);
}
}
public static ApiReturnObject pageManual(Integer pageNumber, Integer pageSize,Integer countNum, List returnObject) {
return new ApiReturnObject(pageNumber+"",pageSize+"",countNum+"",getTotalPages(countNum, pageSize),"00","success",returnObject);
}
public static String getTotalPages(Integer countNum, Integer pageSize) {
if((countNum%pageSize)==0) {
return ((countNum/pageSize))+"";
}else {
return ((countNum/pageSize)+1)+"";
}
}
}

View File

@@ -1,31 +0,0 @@
package com.softdev.system.generator.util;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
public class BasePath {
protected static String contextPath = null;
protected static String basePath = null;
protected static String realPath = null;
public static String getBasePath(HttpServletRequest request) {
contextPath = request.getContextPath();
basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+contextPath+"/";
return basePath;
}
public static String getRealPath(HttpServletRequest request, String path) {
ServletContext context = request.getSession().getServletContext();
realPath = context.getRealPath(path);
realPath = context.getRealPath(path)+"\\";
return realPath;
}
public static String getMyRealPath(HttpServletRequest request, String path) {
ServletContext context = request.getSession().getServletContext();
realPath = context.getRealPath(path);
realPath = context.getRealPath(path);
return realPath;
}
}

View File

@@ -1,59 +0,0 @@
package com.softdev.system.generator.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;
/**
* freemarker tool
*
* @author xuxueli 2018-05-02 19:56:00
*/
@Component
public class FreemarkerTool {
@Autowired
private Configuration configuration;
/**
* process Template Into String
*
* @param template
* @param model
* @return
* @throws IOException
* @throws TemplateException
*/
public String processTemplateIntoString(Template template, Object model)
throws IOException, TemplateException {
StringWriter result = new StringWriter();
template.process(model, result);
return result.toString();
}
/**
* process String
*
* @param templateName
* @param params
* @return
* @throws IOException
* @throws TemplateException
*/
public String processString(String templateName, Map<String, Object> params)
throws IOException, TemplateException {
Template template = configuration.getTemplate(templateName);
String htmlText = processTemplateIntoString(template, params);
return htmlText;
}
}

View File

@@ -1,12 +1,14 @@
package com.softdev.system.generator.util;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Locale;
@@ -18,27 +20,37 @@ import java.util.Map;
* @author xuxueli 2018-05-02 19:56:00
*/
@Slf4j
@Component
public class FreemarkerUtil {
@Autowired
private Configuration configuration;
/**
* 传入需要转义的字符串进行转义
* 20200503 zhengkai.blog.csdn.net
* */
public static String escapeString(String originStr){
return originStr.replaceAll("","\\#").replaceAll("","\\$");
}
/**
* freemarker config
*/
private static Configuration freemarkerConfig = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
static{
String templatePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
int wei = templatePath.lastIndexOf("WEB-INF/classes/");
if (wei > -1) {
templatePath = templatePath.substring(0, wei);
}
try {
freemarkerConfig.setDirectoryForTemplateLoading(new File(templatePath, "templates/xxl-code-generator"));
//2020-06-21 zhengkai 修复path问题导致jar无法运行而本地项目可以运行的bug
freemarkerConfig.setClassForTemplateLoading(FreemarkerUtil.class, "/templates/code-generator");
freemarkerConfig.setTemplateLoader(new ClassTemplateLoader(FreemarkerUtil.class, "/templates/code-generator"));
//freemarkerConfig.setDirectoryForTemplateLoading(new File(templatePath, "templates/code-generator"));
freemarkerConfig.setNumberFormat("#");
freemarkerConfig.setClassicCompatible(true);
freemarkerConfig.setDefaultEncoding("UTF-8");
freemarkerConfig.setLocale(Locale.CHINA);
freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
} catch (IOException e) {
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
@@ -73,7 +85,7 @@ public class FreemarkerUtil {
throws IOException, TemplateException {
Template template = freemarkerConfig.getTemplate(templateName);
String htmlText = processTemplateIntoString(template, params);
String htmlText = escapeString(processTemplateIntoString(template, params));
return htmlText;
}

View File

@@ -1,57 +0,0 @@
package com.softdev.system.generator.util;
/**
* string tool
*
* @author xuxueli 2018-05-02 20:43:25
*/
public class StringPlusUtils {
/**
* 首字母大写
*
* @param str
* @return
*/
public static String upperCaseFirst(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
/**
* 首字母小写
*
* @param str
* @return
*/
public static String lowerCaseFirst(String str) {
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
/**
* 下划线,转换为驼峰式
*
* @param underscoreName
* @return
*/
public static String underlineToCamelCase(String underscoreName) {
StringBuilder result = new StringBuilder();
if (underscoreName != null && underscoreName.trim().length() > 0) {
boolean flag = false;
for (int i = 0; i < underscoreName.length(); i++) {
char ch = underscoreName.charAt(i);
if ("_".charAt(0) == ch) {
flag = true;
} else {
if (flag) {
result.append(Character.toUpperCase(ch));
flag = false;
} else {
result.append(ch);
}
}
}
}
return result.toString();
}
}

View File

@@ -1,294 +1,472 @@
package com.softdev.system.generator.util;
import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.FieldInfo;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author xuxueli 2018-05-02 21:10:45
* @modify zhengk/moshow 20180913
*/
public class TableParseUtil {
/**
* 解析建表SQL生成代码model-dao-xml
*
* @param tableSql
* @return
*/
public static ClassInfo processTableIntoClassInfo(String tableSql, boolean isUnderLineToCamelCase,String tinyintTransType)
throws IOException {
if (tableSql==null || tableSql.trim().length()==0) {
throw new CodeGenerateException("Table structure can not be empty.");
}
tableSql = tableSql.trim().replaceAll("'","`").replaceAll("\"","`").replaceAll("",",").toLowerCase();
// 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("("));
} else {
throw new CodeGenerateException("Table structure anomaly.");
}
//新增处理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);
}
// 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,
if (tableSql.contains("comment=")) {
String classCommentTmp = tableSql.substring(tableSql.lastIndexOf("comment=")+8).replaceAll("`","").trim();
if (classCommentTmp.indexOf(" ")!=classCommentTmp.lastIndexOf(" ")) {
classCommentTmp = classCommentTmp.substring(classCommentTmp.indexOf(" ")+1, classCommentTmp.lastIndexOf(" "));
}
if (classCommentTmp!=null && classCommentTmp.trim().length()>0) {
classComment = classCommentTmp;
}else{
//修复表备注为空问题
classComment = className;
}
}else if(tableSql.contains("comment on table")) {
//COMMENT ON TABLE CT_BAS_FEETYPE IS 'CT_BAS_FEETYPE';
String classCommentTmp = tableSql.substring(tableSql.lastIndexOf("comment on table")+17).trim();
//证明这是一个常规的COMMENT ON TABLE xxx IS 'xxxx'
if (classCommentTmp.contains("`")) {
classCommentTmp = classCommentTmp.substring(classCommentTmp.indexOf("`")+1);
classCommentTmp = classCommentTmp.substring(0,classCommentTmp.indexOf("`"));
classComment = classCommentTmp;
}else{
//非常规的没法分析
classComment = tableName;
}
}else{
//修复表备注为空问题
classComment = tableName;
}
//如果备注跟;混在一起,需要替换掉
classComment=classComment.replaceAll(";","");
// field List
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
// 正常( ) 内的一定是字段相关的定义。
String fieldListTmp = tableSql.substring(tableSql.indexOf("(")+1, tableSql.lastIndexOf(")"));
// 匹配 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 columnLine :fieldLineList) {
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的反馈
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("pctincrease")
&&!columnLine.contains("buffer_pool")&&!columnLine.contains("tablespace")
&&!(columnLine.contains("primary ")&&i>3));
if (specialFlag){
//如果是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,这种情况,判断第一个空格是否比第一个引号前
columnName = columnLine.substring(0, columnLine.indexOf(" "));
// field Name
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
String fieldName;
if(isUnderLineToCamelCase){
fieldName = StringUtils.lowerCaseFirst(StringUtils.underlineToCamelCase(columnName));
if (fieldName.contains("_")) {
fieldName = fieldName.replaceAll("_", "");
}
}else {
fieldName = StringUtils.lowerCaseFirst(columnName);
}
// field class
columnLine = columnLine.substring(columnLine.indexOf("`")+1).trim();
// int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
String fieldClass = Object.class.getSimpleName();
//2018-9-16 zhengk 补充char/clob/blob/json等类型如果类型未知默认为String
//2018-11-22 lshz0088 处理字段类型的时候不严谨columnLine.contains(" int") 类似这种的,可在前后适当加一些空格之类的加以区分,否则当我的字段包含这些字符的时候,产生类型判断问题。
if (columnLine.contains(" int") || columnLine.contains("smallint")) {
fieldClass = Integer.class.getSimpleName();
} else if (columnLine.contains("bigint")) {
fieldClass = Long.class.getSimpleName();
} else if (columnLine.contains("float")) {
fieldClass = Float.class.getSimpleName();
} else if (columnLine.contains("double")) {
fieldClass = Double.class.getSimpleName();
} else if (columnLine.contains("time") || columnLine.contains("date") || columnLine.contains("datetime") || columnLine.contains("timestamp")) {
fieldClass = Date.class.getSimpleName();
} else if (columnLine.contains("varchar") || columnLine.contains(" text")|| columnLine.contains("char")
|| columnLine.contains("clob")||columnLine.contains("blob")||columnLine.contains("json")) {
fieldClass = String.class.getSimpleName();
} else if (columnLine.contains("decimal")||columnLine.contains(" number")) {
//2018-11-22 lshz0088 建议对number类型增加intlongBigDecimal的区分判断
//如果startKh大于等于0则表示有设置取值范围
int startKh=columnLine.indexOf("(");
if(startKh>=0){
int endKh=columnLine.indexOf(")",startKh);
String[] fanwei=columnLine.substring(startKh+1,endKh).split("");
//2019-1-5 zhengk 修复@arthaschan反馈的超出范围错误
//System.out.println("fanwei"+ JSON.toJSONString(fanwei));
// //number(20,6) fanwei["20","6"]
// //number(0,6) fanwei["0","6"]
// //number(20,0) fanwei["20","0"]
// //number(20) fanwei["20"]
//如果括号里是1位或者2位且第二位为0则进行特殊处理。只有有小数位都设置为BigDecimal。
if((fanwei.length>1&&"0".equals(fanwei[1]))||fanwei.length==1){
int length=Integer.parseInt(fanwei[0]);
if(fanwei.length>1) {
length=Integer.valueOf(fanwei[1]);
}
//数字范围9位及一下用Integer大的用Long
if(length<=9){
fieldClass = Integer.class.getSimpleName();
}else{
fieldClass = Long.class.getSimpleName();
}
}else{
//有小数位数一律使用BigDecimal
fieldClass = BigDecimal.class.getSimpleName();
}
}else{
fieldClass = BigDecimal.class.getSimpleName();
}
} else if (columnLine.contains("boolean")) {
//20190910 MOSHOW.K.ZHENG 新增对boolean的处理感谢@violinxsc的反馈以及修复tinyint类型字段无法生成boolean类型问题感谢@hahaYhui的反馈
fieldClass = Boolean.class.getSimpleName();
} else if (columnLine.contains("tinyint") ) {
//20191115 MOSHOW.K.ZHENG 支持对tinyint的特殊处理
fieldClass=tinyintTransType;
} else {
fieldClass = String.class.getSimpleName();
}
// 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();
fieldComment = fieldComment.substring(0,fieldComment.indexOf("`")).trim();
}
}else if (columnLine.contains("comment")) {
String commentTmp = columnLine.substring(columnLine.indexOf("comment")+7).trim();
// '用户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.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);
return codeJavaInfo;
}
}
package com.softdev.system.generator.util;
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.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;
import java.util.regex.Pattern;
/**
* 表格解析Util
* @author zhengkai.blog.csdn.net
*/
public class TableParseUtil {
/**
* 解析DDL SQL生成类信息
* @param paramInfo
* @return
*/
public static ClassInfo processTableIntoClassInfo(ParamInfo paramInfo)
throws IOException {
//process the param
String tableSql=paramInfo.getTableSql();
String nameCaseType=paramInfo.getNameCaseType();
String tinyintTransType=paramInfo.getTinyintTransType();
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("",",").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("("));
} 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);
}
// 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.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 (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(")"));
// 匹配 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 columnLine :fieldLineList) {
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的反馈
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("pctincrease")
&&!columnLine.contains("buffer_pool")&&!columnLine.contains("tablespace")
&&!(columnLine.contains("primary ")&&i>3));
if (specialFlag){
//如果是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,这种情况,判断第一个空格是否比第一个引号前
columnName = columnLine.substring(0, columnLine.indexOf(" "));
// field Name
// 2019-09-08 yj 添加是否下划线转换为驼峰的判断
String fieldName=null;
if(ParamInfo.NAME_CASE_TYPE.CAMEL_CASE.equals(nameCaseType)){
fieldName = StringUtils.lowerCaseFirst(StringUtils.underlineToCamelCase(columnName));
if (fieldName.contains("_")) {
fieldName = fieldName.replaceAll("_", "");
}
}else if(ParamInfo.NAME_CASE_TYPE.UNDER_SCORE_CASE.equals(nameCaseType)){
fieldName = StringUtils.lowerCaseFirst(columnName);
}else if(ParamInfo.NAME_CASE_TYPE.UPPER_UNDER_SCORE_CASE.equals(nameCaseType)){
fieldName = StringUtils.lowerCaseFirst(columnName.toUpperCase());
}else{
fieldName=columnName;
}
// field class
columnLine = columnLine.substring(columnLine.indexOf("`")+1).trim();
// int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
String fieldClass = Object.class.getSimpleName();
//2018-9-16 zhengk 补充char/clob/blob/json等类型如果类型未知默认为String
//2018-11-22 lshz0088 处理字段类型的时候,不严谨columnLine.contains(" int") 类似这种的,可在前后适当加一些空格之类的加以区分,否则当我的字段包含这些字符的时候,产生类型判断问题。
//2020-05-03 MOSHOW.K.ZHENG 优化对所有类型的处理
if (columnLine.contains(" tinyint") ) {
//20191115 MOSHOW.K.ZHENG 支持对tinyint的特殊处理
fieldClass=tinyintTransType;
}
else if (columnLine.contains(" int") || columnLine.contains(" smallint")) {
fieldClass = Integer.class.getSimpleName();
} else if (columnLine.contains(" bigint")) {
fieldClass = Long.class.getSimpleName();
} else if (columnLine.contains(" float")) {
fieldClass = Float.class.getSimpleName();
} else if (columnLine.contains(" double")) {
fieldClass = Double.class.getSimpleName();
} else if (columnLine.contains(" time") || columnLine.contains(" date") || columnLine.contains(" datetime") || columnLine.contains(" timestamp")) {
fieldClass = Date.class.getSimpleName();
} else if (columnLine.contains(" varchar") || columnLine.contains(" text")|| columnLine.contains(" char")
|| columnLine.contains(" clob")||columnLine.contains(" blob")||columnLine.contains(" json")) {
fieldClass = String.class.getSimpleName();
} else if (columnLine.contains(" decimal")||columnLine.contains(" number")) {
//2018-11-22 lshz0088 建议对number类型增加intlongBigDecimal的区分判断
//如果startKh大于等于0则表示有设置取值范围
int startKh=columnLine.indexOf("(");
if(startKh>=0){
int endKh=columnLine.indexOf(")",startKh);
String[] fanwei=columnLine.substring(startKh+1,endKh).split("");
//2019-1-5 zhengk 修复@arthaschan反馈的超出范围错误
//System.out.println("fanwei"+ JSON.toJSONString(fanwei));
// //number(20,6) fanwei["20","6"]
// //number(0,6) fanwei["0","6"]
// //number(20,0) fanwei["20","0"]
// //number(20) fanwei["20"]
//如果括号里是1位或者2位且第二位为0则进行特殊处理。只有有小数位都设置为BigDecimal。
if((fanwei.length>1&&"0".equals(fanwei[1]))||fanwei.length==1){
int length=Integer.parseInt(fanwei[0]);
if(fanwei.length>1) {
length=Integer.valueOf(fanwei[1]);
}
//数字范围9位及一下用Integer大的用Long
if(length<=9){
fieldClass = Integer.class.getSimpleName();
}else{
fieldClass = Long.class.getSimpleName();
}
}else{
//有小数位数一律使用BigDecimal
fieldClass = BigDecimal.class.getSimpleName();
}
}else{
fieldClass = BigDecimal.class.getSimpleName();
}
} else if (columnLine.contains(" boolean")) {
//20190910 MOSHOW.K.ZHENG 新增对boolean的处理感谢@violinxsc的反馈以及修复tinyint类型字段无法生成boolean类型问题感谢@hahaYhui的反馈
fieldClass = Boolean.class.getSimpleName();
} else {
fieldClass = String.class.getSimpleName();
}
// 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();
fieldComment = fieldComment.substring(0,fieldComment.indexOf("`")).trim();
}
}else if (columnLine.contains(" comment")) {
//20200518 zhengkai 修复包含comment关键字的问题
String commentTmp = columnLine.substring(columnLine.lastIndexOf("comment")+7).trim();
// '用户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.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);
return codeJavaInfo;
}
/**
* 解析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
* @author https://github.com/ydq
* @param paramInfo
* @return
*/
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

@@ -2,17 +2,25 @@ server:
port: 1234
servlet:
context-path: /generator
tomcat:
remote-ip-header: x-forward-for
uri-encoding: UTF-8
max-threads: 10
background-processor-delay: 30
basedir: ${user.home}/tomcat/
#tomcat:
# remote-ip-header: x-forward-for
# uri-encoding: UTF-8
# max-threads: 10
# background-processor-delay: 30
# basedir: ${user.home}/tomcat/
undertow:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
# 不要设置过大,如果过大,启动项目会报错:打开文件数过多
io-threads: 4
# 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程
# 它的值设置取决于系统线程执行任务的阻塞系数默认值是IO线程数*8
worker-threads: 64
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
buffer-size: 1024
# 是否分配的直接内存(NIO直接分配的堆外内存)
direct-buffers: true
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
banner:
charset: UTF-8
http:
@@ -32,6 +40,9 @@ spring:
expose-request-attributes: true
expose-session-attributes: true
expose-spring-macro-helpers: true
#template-loader-path: classpath:/templates/
settings:
number_format: 0.##
default_encoding: UTF-8
#template_loader: /templates/
mvc:
static-path-pattern: /static/**

View File

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

View File

@@ -0,0 +1,182 @@
[
{
"id": "10",
"name": "swagger-ui",
"group": "ui",
"description": "swagger-ui"
},
{
"id": "11",
"name": "element-ui",
"group": "ui",
"description": "element-ui"
},
{
"id": "12",
"name": "bootstrap-ui",
"group": "ui",
"description": "bootstrap-ui"
},
{
"id": "13",
"name": "layui-edit",
"group": "ui",
"description": "layui-edit"
},
{
"id": "14",
"name": "layui-list",
"group": "ui",
"description": "layui-list"
},
{
"id": "20",
"name": "controller",
"group": "mybatis",
"description": "controller"
},
{
"id": "21",
"name": "service",
"group": "mybatis",
"description": "service"
},
{
"id": "22",
"name": "service_impl",
"group": "mybatis",
"description": "service_impl"
},
{
"id": "23",
"name": "mapper",
"group": "mybatis",
"description": "mapper"
},
{
"id": "24",
"name": "mybatis",
"group": "mybatis",
"description": "mybatis"
},
{
"id": "25",
"name": "model",
"group": "mybatis",
"description": "model"
},
{
"id": "26",
"name": "mapper2",
"group": "mybatis",
"description": "mapper annotation"
},
{
"id": "30",
"name": "entity",
"group": "jpa",
"description": "entity"
},
{
"id": "31",
"name": "repository",
"group": "jpa",
"description": "repository"
},
{
"id": "32",
"name": "jpacontroller",
"group": "jpa",
"description": "jpacontroller"
},
{
"id": "40",
"name": "jtdao",
"group": "jdbc-template",
"description": "jtdao"
},
{
"id": "41",
"name": "jtdaoimpl",
"group": "jdbc-template",
"description": "jtdaoimpl"
},
{
"id": "50",
"name": "beetlmd",
"group": "beetlsql",
"description": "beetlmd"
},
{
"id": "51",
"name": "beetlentity",
"group": "beetlsql",
"description": "beetlentity"
},
{
"id": "52",
"name": "beetlcontroller",
"group": "beetlsql",
"description": "beetlcontroller"
},
{
"id": "60",
"name": "pluscontroller",
"group": "mybatis-plus",
"description": "pluscontroller"
},
{
"id": "61",
"name": "plusmapper",
"group": "mybatis-plus",
"description": "plusmapper"
},
{
"id": "62",
"name": "plusentity",
"group": "mybatis-plus",
"description": "plusentity"
},
{
"id": "70",
"name": "util",
"group": "util",
"description": "util"
},
{
"id": "71",
"name": "json",
"group": "util",
"description": "json"
},
{
"id": "72",
"name": "xml",
"group": "util",
"description": "xml"
},
{
"id": "80",
"name": "select",
"group": "sql",
"description": "select"
},
{
"id": "81",
"name": "insert",
"group": "sql",
"description": "insert"
},
{
"id": "82",
"name": "update",
"group": "sql",
"description": "update"
},
{
"id": "83",
"name": "delete",
"group": "sql",
"description": "delete"
}
]

View File

@@ -7,9 +7,10 @@ import java.util.List;
import java.util.Map;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@RestController
@RequestMapping("/${classInfo.className?uncap_first}")
public class ${classInfo.className}Controller {

View File

@@ -4,18 +4,22 @@ import java.util.Date;
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
@Data
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Data<#if swagger?exists && swagger==true>
@ApiModel("${classInfo.classComment}")</#if>
public class ${classInfo.className} implements Serializable {
private static final long serialVersionUID = 1L;
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<#list classInfo.fieldList as fieldItem >
/**
* ${fieldItem.fieldComment}
*/
*/<#if swagger?exists && swagger==true>
@ApiModelProperty("${fieldItem.fieldComment}")</#if>
private ${fieldItem.fieldClass} ${fieldItem.fieldName};
</#list>
@@ -23,4 +27,4 @@ public class ${classInfo.className} implements Serializable {
}
</#if>
}
}

View File

@@ -1,26 +0,0 @@
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
@Data
@ApiModel("${classInfo.classComment}")
public class ${classInfo.className}DTO {
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<#list classInfo.fieldList as fieldItem >
@ApiModelProperty("${fieldItem.fieldComment}")
private ${fieldItem.fieldClass} ${fieldItem.fieldName};
</#list>
public ${classInfo.className}() {
}
</#if>
}

View File

@@ -2,9 +2,10 @@
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
public interface I${classInfo.className}DAO {
int add(${classInfo.className} ${classInfo.className?uncap_first});

View File

@@ -6,9 +6,10 @@ import org.springframework.stereotype.Repository;
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Repository
public class ${classInfo.className}DaoImpl implements I${classInfo.className}Dao{

View File

@@ -1,25 +1,39 @@
import java.io.Serializable;
import javax.persistence.*;
package ${packageName}.entity;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Entity
@Data
@Table(name="${classInfo.tableName}")
@Table(name="${classInfo.tableName}")<#if swagger?exists && swagger==true>
@ApiModel("${classInfo.classComment}")</#if>
public class ${classInfo.className} implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<#list classInfo.fieldList as fieldItem >
/**
* ${fieldItem.fieldComment}
*/
*/<#if swagger?exists && swagger==true>
@ApiModelProperty("${fieldItem.fieldComment}")</#if>
@Column(name="${fieldItem.columnName}")
private ${fieldItem.fieldClass} ${fieldItem.fieldName};
</#list>
@@ -27,4 +41,4 @@ public class ${classInfo.className} implements Serializable {
}
</#if>
}
}

View File

@@ -15,9 +15,10 @@ import java.util.List;
import java.util.Map;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@RestController
@RequestMapping("/${classInfo.className?uncap_first}")
public class ${classInfo.className}Controller {

View File

@@ -14,9 +14,10 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Repository
public interface ${classInfo.className}Repository extends JpaRepository<${classInfo.className},Integer> {

View File

@@ -1,19 +1,28 @@
package ${packageName}.controller;
import com.alibaba.fastjson.JSON;
import ${packageName}.entity.${classInfo.className};
import ${packageName}.mapper.${classInfo.className}Mapper;
import ${packageName}.util.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.servlet.ModelAndView;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Slf4j
@RestController
@RequestMapping("/${classInfo.className?uncap_first}")
public class ${classInfo.className}Controller {
@@ -25,14 +34,20 @@ public class ${classInfo.className}Controller {
* 新增或编辑
*/
@PostMapping("/save")
public Object save(${classInfo.className} ${classInfo.className?uncap_first}){
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("id",id))
if(${classInfo.className?uncap_first}!=null){
public Object save(@RequestBody ${classInfo.className} ${classInfo.className?uncap_first}){
log.info("${classInfo.className?uncap_first}:"+JSON.toJSONString(${classInfo.className?uncap_first}));
${classInfo.className} old${classInfo.className} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("${classInfo.className?uncap_first}_id",${classInfo.className?uncap_first}.get${classInfo.className}Id()));
${classInfo.className?uncap_first}.setUpdateTime(new Date());
if(old${classInfo.className}!=null){
${classInfo.className?uncap_first}Mapper.updateById(${classInfo.className?uncap_first});
}else{
${classInfo.className?uncap_first}Mapper.insert(${classInfo.className?uncap_first});
if(${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("${classInfo.className?uncap_first}_name",${classInfo.className?uncap_first}.get${classInfo.className}Name()))!=null){
return ${returnUtil}.ERROR("保存失败,名字重复");
}
return ${returnUtil}.success(${classInfo.className?uncap_first});
${classInfo.className?uncap_first}.setCreateTime(new Date());
${classInfo.className?uncap_first}Mapper.insert(${classInfo.className?uncap_first});
}
return ${returnUtil}.SUCCESS("保存成功");
}
/**
@@ -40,11 +55,12 @@ public class ${classInfo.className}Controller {
*/
@PostMapping("/delete")
public Object delete(int id){
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("id",id))
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("${classInfo.className?uncap_first}_id",id));
if(${classInfo.className?uncap_first}!=null){
return ${returnUtil}.success(${classInfo.className?uncap_first});
${classInfo.className?uncap_first}Mapper.deleteById(id);
return ${returnUtil}.SUCCESS("删除成功");
}else{
return ${returnUtil}.error("没有找到该对象");
return ${returnUtil}.ERROR("没有找到该对象");
}
}
@@ -53,29 +69,85 @@ public class ${classInfo.className}Controller {
*/
@PostMapping("/find")
public Object find(int id){
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("id",id))
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("${classInfo.className?uncap_first}_id",id));
if(${classInfo.className?uncap_first}!=null){
return ${returnUtil}.success(${classInfo.className?uncap_first});
return ${returnUtil}.SUCCESS(${classInfo.className?uncap_first});
}else{
return ${returnUtil}.error("没有找到该对象");
return ${returnUtil}.ERROR("没有找到该对象");
}
}
/**
* 分页查询
* 自动分页查询
*/
@PostMapping("/list")
public Object list(${classInfo.className} ${classInfo.className?uncap_first},
@RequestParam(required = false, defaultValue = "0") int pageNumber,
@RequestParam(required = false, defaultValue = "10") int pageSize) {
public Object list(String searchParams,
@RequestParam(required = false, defaultValue = "0") int page,
@RequestParam(required = false, defaultValue = "10") int limit) {
log.info("page:"+page+"-limit:"+limit+"-json:"+ JSON.toJSONString(searchParams));
//分页构造器
Page<${classInfo.className}> page = new Page<${classInfo.className}>(pageNumber,pageSize);
Page<${classInfo.className}> buildPage = new Page<${classInfo.className}>(page,limit);
//条件构造器
QueryWrapper<${classInfo.className}> queryWrapperw = new QueryWrapper<${classInfo.className}>(${classInfo.className?uncap_first});
QueryWrapper<${classInfo.className}> queryWrapper = new QueryWrapper<${classInfo.className}>();
if(StringUtils.isNotEmpty(searchParams)&&JSON.isValid(searchParams)) {
${classInfo.className} ${classInfo.className?uncap_first} = JSON.parseObject(searchParams, ${classInfo.className}.class);
queryWrapper.eq(StringUtils.isNoneEmpty(${classInfo.className?uncap_first}.get${classInfo.className}Name()), "${classInfo.className?uncap_first}_name", ${classInfo.className?uncap_first}.get${classInfo.className}Name());
}
//执行分页
IPage<${classInfo.className}> pageList = certPersonMapper.selectPage(page, queryWrapperw);
IPage<${classInfo.className}> pageList = ${classInfo.className?uncap_first}Mapper.selectPage(buildPage, queryWrapper);
//返回结果
return ${returnUtil}.success(pageList);
return ${returnUtil}.PAGE(pageList.getRecords(),pageList.getTotal());
}
/**
* 手工分页查询(按需使用)
*/
@PostMapping("/list2")
public ReturnT list2(String searchParams,
@RequestParam(required = false, defaultValue = "0") int page,
@RequestParam(required = false, defaultValue = "10") int limit) {
log.info("searchParams:"+ JSON.toJSONString(searchParams));
//通用模式
${classInfo.className} queryParamDTO = JSON.parseObject(searchParams, ${classInfo.className}.class);
//专用DTO模式
//QueryParamDTO queryParamDTO = JSON.parseObject(searchParams, QueryParamDTO.class);
//queryParamDTO.setPage((page - 1)* limit);
//queryParamDTO.setLimit(limit);
//(page - 1) * limit, limit
List<${classInfo.className}> itemList = ${classInfo.className?uncap_first}Mapper.pageAll(queryParamDTO,(page - 1)* limit,limit);
Integer itemCount = ${classInfo.className?uncap_first}Mapper.countAll(queryParamDTO);
//返回结果
return ReturnT.PAGE(itemList,itemCount);
}
@GetMapping("/list")
public ModelAndView listPage(){
return new ModelAndView("cms/${classInfo.className?uncap_first}-list");
}
@GetMapping("/edit")
public ModelAndView editPage(int id){
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("${classInfo.className?uncap_first}_id",id));
return new ModelAndView("cms/${classInfo.className?uncap_first}-edit","${classInfo.className?uncap_first}",${classInfo.className?uncap_first});
}
/**
* 发布/暂停(如不需要请屏蔽)
*/
@PostMapping("/publish")
public Object publish(int id,Integer status){
${classInfo.className} ${classInfo.className?uncap_first} = ${classInfo.className?uncap_first}Mapper.selectOne(new QueryWrapper<${classInfo.className}>().eq("${classInfo.className?uncap_first}_id",id));
if(${classInfo.className?uncap_first}!=null){
${classInfo.className?uncap_first}.setUpdateTime(new Date());
${classInfo.className?uncap_first}.setStatus(status);
${classInfo.className?uncap_first}Mapper.updateById(${classInfo.className?uncap_first});
return ReturnT.SUCCESS((status==1)?"已发布":"已暂停");
}else if(status.equals(${classInfo.className?uncap_first}.getStatus())){
return ReturnT.SUCCESS("状态不正确");
}else{
return ReturnT.ERROR();
}
}
}

View File

@@ -0,0 +1,35 @@
package ${packageName}.entity;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
/**
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Data<#if swagger?exists && swagger==true>
@ApiModel("${classInfo.classComment}")</#if>
public class ${classInfo.className} implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<#list classInfo.fieldList as fieldItem >
/**
* ${fieldItem.fieldComment}
*/<#if swagger?exists && swagger==true>
@ApiModelProperty("${fieldItem.fieldComment}")</#if>
private ${fieldItem.fieldClass} ${fieldItem.fieldName};
</#list>
public ${classInfo.className}() {
}
</#if>
}

View File

@@ -1,14 +1,38 @@
package ${packageName}.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import ${packageName}.entity.${classInfo.className};
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
@Repository
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Mapper
public interface ${classInfo.className}Mapper extends BaseMapper<${classInfo.className}> {
@Select(
"<script>select t0.* from ${classInfo.tableName} t0 " +
//add here if need left join
"where 1=1" +
<#list classInfo.fieldList as fieldItem >
"<when test='${fieldItem.fieldName}!=null and ${fieldItem.fieldName}!=&apos;&apos; '> and t0.${fieldItem.columnName}=井{${fieldItem.fieldName}}</when> " +
</#list>
//add here if need page limit
//" limit ¥{page},¥{limit} " +
" </script>")
List<${classInfo.className}> pageAll(${classInfo.className} queryParamDTO,int page,int limit);
@Select("<script>select count(1) from ${classInfo.tableName} t0 " +
//add here if need left join
"where 1=1" +
<#list classInfo.fieldList as fieldItem >
"<when test='${fieldItem.fieldName}!=null and ${fieldItem.fieldName}!=&apos;&apos; '> and t0.${fieldItem.columnName}=井{${fieldItem.fieldName}}</when> " +
</#list>
" </script>")
int countAll(${classInfo.className} queryParamDTO);
}

View File

@@ -9,10 +9,10 @@ import java.util.List;
import java.util.Map;
/**
* ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@RestController
@RequestMapping(value = "/${classInfo.className}")
public class ${classInfo.className}Controller {
@@ -21,7 +21,7 @@ public class ${classInfo.className}Controller {
private ${classInfo.className}Service ${classInfo.className?uncap_first}Service;
/**
* [新增]
* 新增
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
@@ -31,7 +31,7 @@ public class ${classInfo.className}Controller {
}
/**
* [刪除]
* 刪除
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
@@ -41,7 +41,7 @@ public class ${classInfo.className}Controller {
}
/**
* [更新]
* 更新
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
@@ -51,7 +51,7 @@ public class ${classInfo.className}Controller {
}
/**
* [查询] 根据主键 id 查询
* 查询 根据主键 id 查询
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
@@ -61,7 +61,7 @@ public class ${classInfo.className}Controller {
}
/**
* [查询] 分页查询
* 查询 分页查询
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/

View File

@@ -4,51 +4,51 @@ import org.springframework.stereotype.Repository;
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Mapper
@Repository
public interface ${classInfo.className}Mapper {
/**
* [新增]
* 新增
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
int insert(${classInfo.className} ${classInfo.className?uncap_first});
/**
* [刪除]
* 刪除
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
int delete(int id);
/**
* [更新]
* 更新
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
int update(${classInfo.className} ${classInfo.className?uncap_first});
/**
* [查询] 根据主键 id 查询
* 查询 根据主键 id 查询
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
${classInfo.className} load(int id);
/**
* [查询] 分页查询
* 查询 分页查询
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/
List<${classInfo.className}> pageList(int offset,int pagesize);
/**
* [查询] 分页查询 count
* 查询 分页查询 count
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
**/

View File

@@ -0,0 +1,56 @@
package ${packageName}.mapper;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @description ${classInfo.classComment}Mapper
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Mapper
@Repository
public interface ${classInfo.className}Mapper {
@Select("select * from ${classInfo.tableName} where ${classInfo.tableName}_id=井{id}")
public ${classInfo.className} getById(Integer id);
@Options(useGeneratedKeys=true,keyProperty="${classInfo.className?uncap_first}Id")
@Insert("insert into ${classInfo.tableName}"
"(<#list classInfo.fieldList as fieldItem >${fieldItem.columnName}<#if fieldItem_has_next>,</#if></#list>)"
"values(<#list classInfo.fieldList as fieldItem >${fieldItem.fieldName}<#if fieldItem_has_next>,</#if>)</#list>")
public Integer insert(${classInfo.className} ${classInfo.className?uncap_first});
@Delete(value = "delete from ${classInfo.tableName} where ${classInfo.tableName}_id=井{${classInfo.className?uncap_first}Id}")
boolean delete(Integer id);
@Update(value = "update ${classInfo.tableName} set "
<#list classInfo.fieldList as fieldItem >
<#if fieldItem.columnName != "id">+" ${fieldItem.columnName}=井{${fieldItem.fieldName}}<#if fieldItem_has_next>,</#if>"</#if>
</#list>
+" where ${classInfo.tableName}_id=井{${classInfo.className?uncap_first}Id} ")
boolean update(${classInfo.className} ${classInfo.className?uncap_first});
@Results(value = {
<#list classInfo.fieldList as fieldItem >
@Result(property = "${fieldItem.fieldName}", column = "${fieldItem.columnName}")<#if fieldItem_has_next>,</#if>
</#list>
})
@Select(value = "select * from ${classInfo.tableName} where ${classInfo.tableName}_id=井{queryParam}")
${classInfo.className} selectOne(String queryParam);
@Results(value = {
<#list classInfo.fieldList as fieldItem >
@Result(property = "${fieldItem.fieldName}", column = "${fieldItem.columnName}")<#if fieldItem_has_next>,</#if>
</#list>
})
@Select(value = "select * from ${classInfo.tableName} where "
<#list classInfo.fieldList as fieldItem >
+" ${fieldItem.columnName}=井{${fieldItem.fieldName}}<#if fieldItem_has_next> or </#if>"
</#list>
)
List<${classInfo.className}> selectList(${classInfo.className} ${classInfo.className?uncap_first});
}

View File

@@ -3,10 +3,12 @@ import java.util.Date;
import java.util.List;
/**
* ${classInfo.classComment}
* @author ${authorName} ${.now?string('yyyy-MM-dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
public class ${classInfo.className} implements Serializable {
private static final long serialVersionUID = 1L;
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
@@ -34,4 +36,4 @@ public class ${classInfo.className} implements Serializable {
</#list>
</#if>
}
}

View File

@@ -1,10 +1,10 @@
import java.util.Map;
/**
* ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
public interface ${classInfo.className}Service {
/**

View File

@@ -7,10 +7,10 @@ import java.util.List;
import java.util.Map;
/**
* ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy/MM/dd')}
*/
* @description ${classInfo.classComment}
* @author ${authorName}
* @date ${.now?string('yyyy-MM-dd')}
*/
@Service
public class ${classInfo.className}ServiceImpl implements ${classInfo.className}Service {
@@ -23,25 +23,25 @@ public class ${classInfo.className}ServiceImpl implements ${classInfo.className}
// valid
if (${classInfo.className?uncap_first} == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "必要参数缺失");
return ${returnUtil}.ERROR("必要参数缺失");
}
${classInfo.className?uncap_first}Mapper.insert(${classInfo.className?uncap_first});
return ReturnT.SUCCESS;
return ${returnUtil}.SUCCESS;
}
@Override
public ReturnT<String> delete(int id) {
int ret = ${classInfo.className?uncap_first}Mapper.delete(id);
return ret>0?ReturnT.SUCCESS:ReturnT.FAIL;
return ret>0?${returnUtil}.SUCCESS():${returnUtil}.ERROR();
}
@Override
public ReturnT<String> update(${classInfo.className} ${classInfo.className?uncap_first}) {
int ret = ${classInfo.className?uncap_first}Mapper.update(${classInfo.className?uncap_first});
return ret>0?ReturnT.SUCCESS:ReturnT.FAIL;
return ret>0?${returnUtil}.SUCCESS():${returnUtil}.ERROR();
}

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layuimini</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="¥{request.contextPath}/static/lib/layui-v2.5.5/css/layui.css" media="all">
<link rel="stylesheet" href="¥{request.contextPath}/static/css/public.css" media="all">
<style>
body {
background-color: #ffffff;
}
</style>
</head>
<body>
<div class="layui-form layuimini-form">
<input type="hidden" name="${classInfo.className?uncap_first}Id" value="" class="layui-input">
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<#list classInfo.fieldList as fieldItem >
<div class="layui-form-item">
<label class="layui-form-label required">${fieldItem.fieldComment}</label>
<div class="layui-input-block">
<input type="text" name="${fieldItem.fieldName}" lay-verify="required" lay-reqtext="${fieldItem.fieldComment}不能为空" placeholder="请输入${fieldItem.fieldComment}" value="¥{(${classInfo.className?uncap_first}.${fieldItem.fieldName})!!}" class="layui-input">
<#--<tip>${fieldItem.fieldComment}</tip>-->
</div>
</div>
</#list>
</#if>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
<script src="¥{request.contextPath}/static/lib/layui-v2.5.5/layui.js" charset="utf-8"></script>
<script>
layui.use(['form'], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.$;
//监听提交
form.on('submit(saveBtn)', function (data) {
$.ajax({
type: 'POST',
url: "¥{request.contextPath}/${classInfo.className?uncap_first}/save",
data:JSON.stringify(data.field),
dataType: "json",
contentType: "application/json",
success: function (responseData) {
if (responseData.code === 200) {
layer.msg(responseData.msg, function () {
// 关闭弹出层
//layer.close(index);
var iframeIndex = parent.layer.getFrameIndex(window.name);
parent.layer.close(iframeIndex);
parent.searchBtn.click();
});
} else {
layer.msg(responseData.msg, function () {
//window.location = '/index.html';
});
}
}
});
return false;
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,230 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layuimini</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="¥{request.contextPath}/static/lib/layui-v2.5.5/css/layui.css" media="all">
<link rel="stylesheet" href="¥{request.contextPath}/static/css/public.css" media="all">
</head>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<fieldset class="table-search-fieldset">
<legend>搜索信息</legend>
<div style="margin: 10px 10px 10px 10px">
<form class="layui-form layui-form-pane" action="">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">${classInfo.classComment}Id</label>
<div class="layui-input-inline">
<input type="text" name="${classInfo.className?uncap_first}Id" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">${classInfo.classComment}名称</label>
<div class="layui-input-inline">
<input type="text" name="${classInfo.className?uncap_first}Name" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button id="searchBtn" type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
</div>
</div>
</form>
</div>
</fieldset>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add"> <i class="layui-icon layui-icon-addition"></i>${classInfo.classComment} </button>
<#-- <button class="layui-btn layui-btn-normal layui-btn-sm layui-btn-danger data-delete-btn" lay-event="del"> 删除${classInfo.classComment} </button>-->
</div>
</script>
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
<script type="text/html" id="currentTableBar">
<a class="layui-btn layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
</script>
<script type="text/html" id="typeTemplate">
{{# if(d.type == '1'){ }}
常规
{{# } else if(d.type =='2') { }}
专项
{{# } else { }}
其它
{{# } }}
</script>
<script type="text/html" id="statusTemplate">
{{# if(d.status == '1' ){ }}
<i class="layui-icon layui-icon-ok"></i>已发布
{{# } else { }}
- 未发布
{{# } }}
</script>
</div>
</div>
<script src="¥{request.contextPath}/static/lib/layui-v2.5.5/layui.js" charset="utf-8"></script>
<script>
layui.use(['form', 'table'], function () {
var $ = layui.jquery,
form = layui.form,
table = layui.table;
table.render({
elem: '#currentTableId',
method: 'post',
url: '¥{request.contextPath}/${classInfo.className?uncap_first}/list',
toolbar: '#toolbarDemo',
defaultToolbar: ['filter', 'exports', 'print', {
title: '提示',
layEvent: 'LAYTABLE_TIPS',
icon: 'layui-icon-tips'
}],
cols: [[
{type: "checkbox", width: 50, fixed: "left"},
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<#list classInfo.fieldList as fieldItem >
{field: '${fieldItem.fieldName}', title: '${fieldItem.fieldComment}', sort: true}, <#if fieldItem_has_next> </#if>
</#list>
</#if>
/* 需要时间请自行解封
{title: '创建时间', sort: true,templet: "<div>{{layui.util.toDateString(d.createTime, 'yyyy-MM-dd')}}</div>"},
{title: '修改时间', sort: true,templet: "<div>{{layui.util.toDateString(d.updateTime, 'yyyy-MM-dd')}}</div>"},
*/
{title: '操作', minWidth: 400, templet: '#currentTableBar', fixed: "right", align: "center"}
]],
limits: [20 , 50 , 100],
limit: 20,
page: true
});
var result;
/**
* submit(data-search-btn):监听搜索操作
*/
form.on('submit(data-search-btn)', function (data) {
result = JSON.stringify(data.field);
//执行搜索重载
table.reload('currentTableId', {
page: {
curr: 1
}
, where: {
searchParams: result
}
}, 'data');
return false;
});
var searchBtn = $("#searchBtn");
/**
* toolbar监听事件:表格添加按钮
*/
table.on('toolbar(currentTableFilter)', function (obj) {
if (obj.event === 'add') {
var index = layer.open({
title: '添加',
type: 2,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: ['1000px', '700px'],
content: '¥{request.contextPath}/${classInfo.className?uncap_first}/edit?id=0',
});
return false;
}else if(obj.event === 'del') {
var checkStatus = table.checkStatus('currentTableId')
, data = checkStatus.data;
layer.alert(JSON.stringify(data));
}
});
/**
* checkbox(currentTableFilter):表格复选框选择
*/
table.on('checkbox(currentTableFilter)', function (obj) {
//console.log(obj)
});
/**
* tool监听事件:表格编辑删除等功能按钮
*/
table.on('tool(currentTableFilter)', function (obj) {
var data = obj.data;
if (obj.event === 'edit') {
var index = layer.open({
title: '编辑',
type: 2,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: ['1000px', '700px'],
content: '¥{request.contextPath}/${classInfo.className?uncap_first}/edit?id='+obj.data.${classInfo.className?uncap_first}Id,
});
return false;
} else if (obj.event === 'delete') {
layer.confirm('确认删除该记录吗?', function (index) {
$.ajax({
type: 'POST',
url: "¥{request.contextPath}/${classInfo.className?uncap_first}/delete",
data:{"id":obj.data.${classInfo.className?uncap_first}Id},
success: function (responseData) {
if (responseData.code === 200) {
layer.msg(responseData.msg, function () {
obj.del();
});
} else {
layer.msg(responseData.msg, function () {
});
}
}
});
layer.close(index);
});
}else if (obj.event === 'publish') {
layer.confirm('确定要发布吗?', function (index) {
$.ajax({
type: 'POST',
url: "¥{request.contextPath}/${classInfo.className?uncap_first}/publish",
data:{"id":obj.data.${classInfo.className?uncap_first}Id,"status":"1"},
success: function (responseData) {
searchBtn.click();
layer.msg(responseData.msg, function () {
});
}
});
layer.close(index);
});
}else if (obj.event === 'unpublish') {
layer.confirm('确定要停止吗?', function (index) {
$.ajax({
type: 'POST',
url: "¥{request.contextPath}/${classInfo.className?uncap_first}/publish",
data:{"id":obj.data.${classInfo.className?uncap_first}Id,"status":"0"},
success: function (responseData) {
searchBtn.click();
layer.msg(responseData.msg, function () {
});
}
});
layer.close(index);
});
}
});
});
</script>
<script>
</script>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
{
<#list classInfo.fieldList as fieldItem>
"${fieldItem.fieldName}":""<#if fieldItem_has_next>,</#if>
</#list>
}
</#if>

View File

@@ -13,4 +13,9 @@ ${fieldItem.fieldClass} ${fieldItem.fieldName} = ${classInfo.className?uncap_fir
// ${fieldItem.fieldComment}
${classInfo.className?uncap_first}.set${fieldItem.fieldName?cap_first}();
</#list>
<#list classInfo.fieldList as fieldItem>
// ${fieldItem.fieldComment}
${classInfo.className?uncap_first}.set${fieldItem.fieldName?cap_first}(${classInfo.className?uncap_first}2.get${fieldItem.fieldName?cap_first}(););
</#list>
</#if>

View File

@@ -0,0 +1,11 @@
<!--
${classInfo.classComment}对象Get Set
@author ${authorName} ${.now?string('yyyy-MM-dd')}
-->
<#if classInfo.fieldList?exists && classInfo.fieldList?size gt 0>
<${classInfo.className}>
<#list classInfo.fieldList as fieldItem>
<${fieldItem.fieldName}></${fieldItem.fieldName}>
</#list>
</${classInfo.className}>
</#if>

View File

@@ -16,6 +16,8 @@
<link href="//cdn.staticfile.org/codemirror/5.48.4/codemirror.min.css" rel="stylesheet">
<link href="//cdn.bootcss.com/jquery-toast-plugin/1.3.2/jquery.toast.min.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
@@ -32,10 +34,10 @@
<script src="//cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
<!-- Bootstrap -->
<script src="//cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="//cdn.bootcss.com/jquery-toast-plugin/1.3.2/jquery.toast.min.js"></script>
<!-- FastClick -->
<script src="//cdn.staticfile.org/fastclick/1.0.6/fastclick.min.js"></script>
<script src="//cdn.staticfile.org/jQuery-slimScroll/1.3.8/jquery.slimscroll.min.js"></script>
<script src="//cdn.staticfile.org/layer/2.3/layer.js"></script>
<script src="//cdn.staticfile.org/codemirror/5.48.4/codemirror.min.js"></script>
<script src="//cdn.staticfile.org/codemirror/5.48.4/addon/display/placeholder.min.js"></script>
<script src="//cdn.staticfile.org/codemirror/5.48.4/mode/clike/clike.min.js"></script>

View File

@@ -1,316 +1,425 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SQL转Java JPA、MYBATIS实现类代码生成平台</title>
<meta name="keywords" content="sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现">
<#import "common/common-import.ftl" as netCommon>
<@netCommon.commonStyle />
<@netCommon.commonScript />
<#--<script src="${request.contextPath}/static/js/index-new.js"></script>-->
<script>
<@netCommon.viewerCounter />
$(function () {
/**
* 初始化 table sql 3
*/
var ddlSqlArea = CodeMirror.fromTextArea(document.getElementById("ddlSqlArea"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-sql",
lineWrapping:false,
readOnly:false,
foldGutter: true,
gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
ddlSqlArea.setSize('auto','auto');
// controller_ide
var genCodeArea = CodeMirror.fromTextArea(document.getElementById("genCodeArea"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-java",
lineWrapping:true,
readOnly:true,
foldGutter: true,
gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
genCodeArea.setSize('auto','auto');
var codeData;
/**
* 生成代码
*/
$('#btnGenCode').click(function () {
var tableSql = ddlSqlArea.getValue();
$.ajax({
type: 'POST',
url: base_url + "/genCode",
data: {
"tableSql": tableSql,
"packageName":$("#packageName").val(),
"returnUtil":$("#returnUtil").val(),
"authorName":$("#authorName").val(),
"isUnderLineToCamelCase":$("#isUnderLineToCamelCase").val()
},
dataType: "json",
success: function (data) {
if (data.code == 200) {
layer.msg("代码生成成功");
codeData = data.data;
genCodeArea.setValue(codeData.beetlentity);
genCodeArea.setSize('auto', 'auto');
} else {
layer.open({
icon: '2',
content: (data.msg || '代码生成失败')
});
}
}
});
});
/**
* 按钮事件组
*/
$('.generator').bind('click', function () {
if (!$.isEmptyObject(codeData)) {
var id = this.id;
genCodeArea.setValue(codeData[id]);
genCodeArea.setSize('auto', 'auto');
}
});
/**
* 捐赠
*/
function donate(){
layer.open({
type: 1,
area : ['712px' , '480px'],
shadeClose: true, //点击遮罩关闭
content: '<img src="http://upyun.bejson.com/img/zhengkai.png"></img>'
});
}
$('#donate1').on('click', function(){
donate();
});
$('#donate2').on('click', function(){
donate();
});
$('#btnCopy').on('click', function(){
if(!$.isEmptyObject(genCodeArea.getValue())&&!$.isEmptyObject(navigator)&&!$.isEmptyObject(navigator.clipboard)){
navigator.clipboard.writeText(genCodeArea.getValue());
layer.msg("复制成功");
}
});
});
</script>
</head>
<body style="background-color: #e9ecef">
<div class="container">
<nav class="navbar navbar-dark bg-primary btn-lg">
<a class="navbar-brand" href="http://www.bejson.com">BeJSON在线工具站</a>
<ul class="nav navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="http://zhengkai.blog.csdn.net">大狼狗CSDN</a>
</li>
</ul>
</nav>
</div>
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<h2>Spring Boot Code Generator!</h2>
<p class="lead">
√基于SpringBoot2+Freemarker的代码生成器√以释放双手为目的√支持mysql/oracle/pgsql三大数据库<br>
√用DDL-SQL语句生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL相关代码。<br>
欢迎大家多多提交模板和交流想法如果发现有SQL语句不能识别请<a href="https://github.com/moshowgame/SpringBootCodeGenerator/issues">留言</a>,同时欢迎大家提<a href="https://github.com/moshowgame/SpringBootCodeGenerator/pulls">PR</a>和<a href="#" id="donate1">点击赞赏</a>,谢谢!
</p>
<hr>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">作者名称</span>
</div>
<input type="text" class="form-control" id="authorName" name="authorName" placeholder="大狼狗">
<div class="input-group-prepend">
<span class="input-group-text">返回封装</span>
</div>
<input type="text" class="form-control" id="returnUtil" name="returnUtil" placeholder="ApiReturnObject">
<div class="input-group-prepend">
<span class="input-group-text">包名路径</span>
</div>
<input type="text" class="form-control" id="packageName" name="packageName" placeholder="com.softdev.system">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">tinyint转换类型</span>
</div>
<select type="text" class="form-control" id="tinyintTransType"
name="tinyintTransType">
<option value="boolean">boolean</option>
<option value="Boolean">Boolean</option>
<option value="Integer">Integer</option>
<option value="int">int</option>
</select>
<div class="input-group-prepend">
<span class="input-group-text">是否转换下划线为驼峰</span>
</div>
<select type="text" class="form-control" id="isUnderLineToCamelCase"
name="isUnderLineToCamelCase">
<option value="true">转换</option>
<option value="false">不转换</option>
</select>
</div>
<textarea id="ddlSqlArea" placeholder="请输入表结构信息..." class="form-control btn-lg" style="height: 250px;">
CREATE TABLE `userinfo` (
`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` varchar(255) NOT NULL COMMENT '用户名',
`addtime` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息'
</textarea><br>
<p><button class="btn btn-primary btn-lg disabled" id="btnGenCode" role="button">开始生成 »</button> <button class="btn alert-secondary" id="btnCopy">一键复制</button></p>
<hr>
<!-- Example row of columns -->
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">通用实体</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="model">entity(set/get)</button>
<button type="button" class="btn btn-default generator" id="beetlentity">entity(lombok)</button>
</div>
</div>
<div class="btn-toolbar col-md-7" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">Mybatis</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="mybatis">mybatis</button>
<button type="button" class="btn btn-default generator" id="mapper">mapper</button>
<button type="button" class="btn btn-default generator" id="service">service</button>
<button type="button" class="btn btn-default generator" id="service_impl">service_impl</button>
<button type="button" class="btn btn-default generator" id="controller">controller</button>
</div>
</div>
</div>
<!-- Example row of columns -->
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">MybatisPlus</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="plusmapper">mapper</button>
<button type="button" class="btn btn-default generator" id="pluscontroller">controller</button>
</div>
</div>
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">UI</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="swagger-ui">swagger-ui</button>
<button type="button" class="btn btn-default generator" id="element-ui">element-ui</button>
<button type="button" class="btn btn-default generator" id="bootstrap-ui">bootstrap-ui</button>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">BeetlSQL</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="beetlmd">beetlmd</button>
<button type="button" class="btn btn-default generator" id="beetlcontroller">beetlcontroller</button>
</div>
</div>
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">JPA</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="entity">jpa-entity</button>
<button type="button" class="btn btn-default generator" id="repository">repository</button>
<button type="button" class="btn btn-default generator" id="jpacontroller">controller</button>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">JdbcTemplate</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="jtdaoimpl">daoimpl</button>
<button type="button" class="btn btn-default generator" id="jtdao">dao</button>
</div>
</div>
<div class="btn-toolbar col-md-7" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">SQL</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="select">select</button>
<button type="button" class="btn btn-default generator" id="insert">insert</button>
<button type="button" class="btn btn-default generator" id="update">update</button>
<button type="button" class="btn btn-default generator" id="delete">delete</button>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">DTO</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="beetlentitydto">entitydto(lombok+swagger)</button>
</div>
</div>
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled" id="btnGroupAddon">Util</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="util">bean get set</button>
</div>
</div>
</div>
<hr>
<textarea id="genCodeArea" class="form-control btn-lg" ></textarea>
</div>
</div>
<@netCommon.commonFooter />
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SQL转Java JPA、MYBATIS实现类代码生成平台</title>
<meta name="keywords" content="sql转实体类,sql转DAO,SQL转service,SQL转JPA实现,SQL转MYBATIS实现">
<#import "common/common-import.ftl" as netCommon>
<@netCommon.commonStyle />
<@netCommon.commonScript />
<script>
<@netCommon.viewerCounter />
$(function () {
/**
* 初始化 table sql 3
*/
var ddlSqlArea = CodeMirror.fromTextArea(document.getElementById("ddlSqlArea"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-sql",
lineWrapping:false,
readOnly:false,
foldGutter: true,
//keyMap:"sublime",
gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
ddlSqlArea.setSize('auto','auto');
// controller_ide
var genCodeArea = CodeMirror.fromTextArea(document.getElementById("genCodeArea"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-java",
lineWrapping:true,
readOnly:false,
foldGutter: true,
//keyMap:"sublime",
gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
genCodeArea.setSize('auto','auto');
var codeData;
// 使用var jsonObj = $("#formId").serializeObject();
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
var historyCount=0;
//初始化清除session
if (window.sessionStorage){
//修复当F5刷新的时候session没有清空各个值但是页面的button没了。
sessionStorage.clear();
}
/**
* 生成代码
*/
$('#btnGenCode').click(function () {
var jsonData = {
"tableSql": ddlSqlArea.getValue(),
"packageName":$("#packageName").val(),
"returnUtil":$("#returnUtil").val(),
"authorName":$("#authorName").val(),
"dataType":$("#dataType").val(),
"tinyintTransType":$("#tinyintTransType").val(),
"nameCaseType":$("#nameCaseType").val(),
"swagger":$("#isSwagger").val()
};
$.ajax({
type: 'POST',
url: base_url + "/genCode",
data:(JSON.stringify(jsonData)),
dataType: "json",
contentType: "application/json",
success: function (data) {
if (data.code === 200) {
codeData = data.data;
genCodeArea.setValue(codeData.beetlentity);
genCodeArea.setSize('auto', 'auto');
$.toast("√ 代码生成成功");
//添加历史记录
addHistory(codeData);
} else {
$.toast("× 代码生成失败 :"+data.msg);
}
}
});
return false;
});
/**
* 切换历史记录
*/
function getHistory(tableName){
if (window.sessionStorage){
var valueSession = sessionStorage.getItem(tableName);
codeData = JSON.parse(valueSession);
$.toast("$ 切换历史记录成功:"+tableName);
genCodeArea.setValue(codeData.entity);
}else{
console.log("浏览器不支持sessionStorage");
}
}
/**
* 添加历史记录
*/
function addHistory(data){
if (window.sessionStorage){
//console.log(historyCount);
if(historyCount>=9){
$("#history").find(".btn:last").remove();
historyCount--;
}
var tableName=data.tableName;
var valueSession = sessionStorage.getItem(tableName);
if(valueSession!==undefined && valueSession!=null){
sessionStorage.removeItem(tableName);
}else{
$("#history").prepend('<button id="his-'+tableName+'" type="button" class="btn">'+tableName+'</button>');
//$("#history").prepend('<button id="his-'+tableName+'" onclick="getHistory(\''+tableName+'\');" type="button" class="btn">'+tableName+'</button>');
$("#his-"+tableName).bind('click', function () {getHistory(tableName)});
}
sessionStorage.setItem(tableName,JSON.stringify(data));
historyCount++;
}else{
console.log("浏览器不支持sessionStorage");
}
}
/**
* 按钮事件组
*/
$('.generator').bind('click', function () {
if (!$.isEmptyObject(codeData)) {
var id = this.id;
genCodeArea.setValue(codeData[id]);
genCodeArea.setSize('auto', 'auto');
}
});
/**
* 捐赠
*/
function donate(){
if($("#donate").attr("show")=="no"){
$("#donate").html('<img src="https://raw.githubusercontent.com/moshowgame/SpringBootCodeGenerator/master/donate.png"></img>');
$("#donate").attr("show","yes");
}else{
$("#donate").html('<p>谢谢赞赏!</p>');
$("#donate").attr("show","no");
}
}
$('#donate1').on('click', function(){
donate();
});
$('#donate2').on('click', function(){
donate();
});
$('#btnCopy').on('click', function(){
if(!$.isEmptyObject(genCodeArea.getValue())&&!$.isEmptyObject(navigator)&&!$.isEmptyObject(navigator.clipboard)){
navigator.clipboard.writeText(genCodeArea.getValue());
$.toast("√ 复制成功");
}
});
function getVersion(){
var gitVersion ;
$.ajax({
type: 'GET',
url: "https://raw.githubusercontent.com/moshowgame/SpringBootCodeGenerator/master/generator-web/src/main/resources/static/version.json",
dataType: "json",
success: function (data) {
gitVersion = data.version;
$.ajax({
type: 'GET',
url: base_url + "/static/version.json",
dataType: "json",
success: function (data) {
$.toast("#当前版本:"+data.version+" | github:"+gitVersion);
}
});
}
});
}
$('#version').on('click', function(){
getVersion();
});
});
</script>
</head>
<body style="background-color: #e9ecef">
<div class="container">
<nav class="navbar navbar-dark bg-primary btn-lg">
<a class="navbar-brand" href="http://www.bejson.com">BeJSON在线工具站</a>
<ul class="nav navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="http://zhengkai.blog.csdn.net">zhengkai.blog.csdn.net</a>
</li>
</ul>
</nav>
</div>
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<h2>Spring Boot Code Generator!</h2>
<p class="lead">
√基于SpringBoot2+Freemarker的<a class="lead" href="https://github.com/moshowgame/SpringBootCodeGenerator">代码生成器</a><br>
√以解放双手为目的减少大量重复的CRUD工作<br>
√支持mysql/oracle/pgsql三大数据库<br>
√用DDL-SQL语句生成JPA/JdbcTemplate/Mybatis/MybatisPlus/BeetlSQL相关代码。<br>
如果发现有SQL语句不能识别请<a href="https://github.com/moshowgame/SpringBootCodeGenerator/issues">留言</a>,同时欢迎大家提<a href="https://github.com/moshowgame/SpringBootCodeGenerator/pulls">PR</a>和<a href="#" id="donate1">赞赏</a>,谢谢!<a id="version" href="#">查看版本</a>
</p>
<div id="donate" class="container" show="no"></div>
<hr>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">作者名称</span>
</div>
<input type="text" class="form-control" id="authorName" name="authorName" value="zhengkai.blog.csdn.net">
<div class="input-group-prepend">
<span class="input-group-text">返回封装</span>
</div>
<input type="text" class="form-control" id="returnUtil" name="returnUtil" value="ReturnT">
<div class="input-group-prepend">
<span class="input-group-text">包名路径</span>
</div>
<input type="text" class="form-control" id="packageName" name="packageName" value="com.softdev.system">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">数据类型</span>
</div>
<select type="text" class="form-control" id="dataType"
name="dataType">
<option value="sql">ddl-sql</option>
<option value="json">json</option>
<option value="insert-sql">insert-sql</option>
<#--<option value="sql-regex">sql-regex</option>-->
</select>
<div class="input-group-prepend">
<span class="input-group-text">tinyint转换类型</span>
</div>
<select type="text" class="form-control" id="tinyintTransType"
name="tinyintTransType">
<option value="boolean">boolean</option>
<option value="Boolean">Boolean</option>
<option value="Integer">Integer</option>
<option value="int">int</option>
<option value="String">String</option>
</select>
<div class="input-group-prepend">
<span class="input-group-text">命名转换规则</span>
</div>
<select type="text" class="form-control" id="nameCaseType"
name="nameCaseType">
<option value="CamelCase">驼峰</option>
<option value="UnderScoreCase">下划线</option>
<#--<option value="UpperUnderScoreCase">大写下划线</option>-->
</select>
<div class="input-group-prepend">
<span class="input-group-text">swagger-ui</span>
</div>
<select type="text" class="form-control" id="isSwagger"
name="isSwagger">
<option value="false">关闭</option>
<option value="true">开启</option>
</select>
</div>
<textarea id="ddlSqlArea" placeholder="请输入表结构信息..." class="form-control btn-lg" style="height: 250px;">
CREATE TABLE 'userinfo' (
'user_id' int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
'user_name' varchar(255) NOT NULL COMMENT '用户名',
'addtime' datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY ('user_id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息'
</textarea><br>
<p><button class="btn btn-primary btn-lg disabled" id="btnGenCode" role="button" data-toggle="popover" data-content="">开始生成 »</button> <button class="btn alert-secondary" id="btnCopy">一键复制</button></p>
<div id="history" class="btn-group" role="group" aria-label="Basic example"></div>
<hr>
<!-- Example row of columns -->
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">通用实体</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="model">entity(set/get)</button>
<button type="button" class="btn btn-default generator" id="beetlentity">entity(lombok)</button>
</div>
</div>
<div class="btn-toolbar col-md-7" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">Mybatis</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="mybatis">ibatisXml</button>
<button type="button" class="btn btn-default generator" id="mapper">mapper</button>
<button type="button" class="btn btn-default generator" id="mapper2">mapper2</button>
<button type="button" class="btn btn-default generator" id="service">service</button>
<button type="button" class="btn btn-default generator" id="service_impl">serviceImpl</button>
<button type="button" class="btn btn-default generator" id="controller">controller</button>
</div>
</div>
</div>
<!-- Example row of columns -->
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">MybatisPlus</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="plusentity">entity</button>
<button type="button" class="btn btn-default generator" id="plusmapper">mapper</button>
<button type="button" class="btn btn-default generator" id="pluscontroller">controller</button>
</div>
</div>
<div class="btn-toolbar col-md-7" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">UI</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="swagger-ui">swagger-ui</button>
<button type="button" class="btn btn-default generator" id="element-ui">element-ui</button>
<button type="button" class="btn btn-default generator" id="bootstrap-ui">bootstrap-ui</button>
<button type="button" class="btn btn-default generator" id="layui-edit">layui-edit</button>
<button type="button" class="btn btn-default generator" id="layui-list">layui-list</button>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">BeetlSQL</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="beetlmd">beetlmd</button>
<button type="button" class="btn btn-default generator" id="beetlcontroller">beetlcontroller</button>
</div>
</div>
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">JPA</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="entity">jpa-entity</button>
<button type="button" class="btn btn-default generator" id="repository">repository</button>
<button type="button" class="btn btn-default generator" id="jpacontroller">controller</button>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">JdbcTemplate</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="jtdaoimpl">daoimpl</button>
<button type="button" class="btn btn-default generator" id="jtdao">dao</button>
</div>
</div>
<div class="btn-toolbar col-md-7" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">SQL</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="select">select</button>
<button type="button" class="btn btn-default generator" id="insert">insert</button>
<button type="button" class="btn btn-default generator" id="update">update</button>
<button type="button" class="btn btn-default generator" id="delete">delete</button>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="btn-toolbar col-md-5" role="toolbar" aria-label="Toolbar with button groups">
<div class="input-group">
<div class="input-group-prepend">
<div class="btn btn-secondary disabled setWidth" id="btnGroupAddon">Util</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="First group">
<button type="button" class="btn btn-default generator" id="util">bean get set</button>
<button type="button" class="btn btn-default generator" id="json">json</button>
<button type="button" class="btn btn-default generator" id="xml">xml</button>
</div>
</div>
</div>
<hr>
<textarea id="genCodeArea" class="form-control btn-lg" ></textarea>
</div>
</div>
<@netCommon.commonFooter />
</body>
</html>

64
pom.xml
View File

@@ -5,7 +5,7 @@
<groupId>com.softdev.system</groupId>
<artifactId>SpringBootCodeGenerator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>2.0</version>
<packaging>pom</packaging>
<parent>
@@ -31,6 +31,18 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除Tomcat依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加 Undertow依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
@@ -62,26 +74,11 @@
<version>1.2.8.RELEASE</version>
</dependency>-->
<!-- Hutool超级工具类 http://hutool.mydoc.io/ -->
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.1</version>
</dependency>
<!-- lombok -->
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
<version>1.18.12</version>
</dependency>
<!-- freemarker -->
@@ -90,28 +87,6 @@
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- java.lang.ClassNotFoundException: javax.xml.bind.JAXBException/javax.xml.bind.annotation.XmlType问题解决 -->
<!--<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>-->
</dependencies>
@@ -134,7 +109,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<version>3.8.1</version>
<configuration>
<skip>true</skip>
<compilerId>javac</compilerId>
@@ -156,13 +131,13 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<version>3.1.0</version>
<configuration>
<!--<failOnMissingWebXml>false</failOnMissingWebXml>-->
<includeEmptyDirs>true</includeEmptyDirs>
</configuration>
</plugin>
<plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
@@ -170,11 +145,10 @@
<failOnMissingWebXml>false</failOnMissingWebXml>
<warSourceExcludes>upload/**</warSourceExcludes>
</configuration>
</plugin>
</plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.4.RELEASE</version>
<executions>
<execution>
<goals>