├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
├── java
└── com
│ └── greedystar
│ └── generator
│ ├── application
│ └── Main.java
│ ├── convertor
│ ├── DefaultConvertor.java
│ └── TypeConvertor.java
│ ├── db
│ ├── ConnectionUtil.java
│ └── DataBaseFactory.java
│ ├── entity
│ ├── ColumnInfo.java
│ ├── Configuration.java
│ ├── Constant.java
│ ├── IdStrategy.java
│ └── Mode.java
│ ├── invoker
│ ├── Many2ManyInvoker.java
│ ├── Many2OneInvoker.java
│ ├── One2ManyInvoker.java
│ ├── SingleInvoker.java
│ └── base
│ │ ├── AbstractBuilder.java
│ │ ├── AbstractInvoker.java
│ │ └── Invoker.java
│ ├── task
│ ├── ControllerTask.java
│ ├── DaoTask.java
│ ├── EntityTask.java
│ ├── InterfaceTask.java
│ ├── MapperTask.java
│ ├── ServiceTask.java
│ └── base
│ │ └── AbstractTask.java
│ └── utils
│ ├── ConfigUtil.java
│ ├── ConvertorUtil.java
│ ├── FileUtil.java
│ ├── ForEachUtil.java
│ ├── FreemarkerConfigUtil.java
│ ├── IOUtils.java
│ ├── StringUtil.java
│ └── TaskQueue.java
└── resources
└── ftls
├── Controller.ftl
├── Dao.ftl
├── Entity.ftl
├── Interface.ftl
├── Mapper.ftl
└── Service.ftl
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | out/
3 | META-INF/
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### IntelliJ IDEA ###
8 | .idea
9 | *.iws
10 | *.iml
11 | *.ipr
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # 欢迎来到 Generator
3 |
4 | Generator 是一款基于数据库表生成Java代码的工具,代码模板使用当前主流Java框架: **Spring, SpringMVC, Mybatis(Mybatis-Plus、JPA)** 组织,能够减少繁琐的重复性工作,让开发人员更专注于技术和性能,提高工作效率和编码热情。
5 |
6 | 你可以使用Generator:
7 | > * 根据数据库业务表生成实体类
8 | > * 生成包含简单的增、删、查、改操作的Mapper文件
9 | > * 生成Controller、Service、Dao代码
10 |
11 | ### Release note:
12 | * v1.0.0 框架基本功能,支持连接本地MySql数据库
13 | * v1.0.1 修复默认模板文件中存在的错误
14 | * v1.1.0 支持连接远程MySql、Oracle、SqlServer数据库(可配置)
15 | * v1.2.0 添加列名到属性名的映射规则;代码生成任务多线程;可配置生成策略等
16 | * v1.2.1 Service层添加接口和实现类的支持
17 | * v1.3.0 添加实体的类注释和属性注释,自动创建代码生成目录,可自定义类型转换器,解决生成文件冲突
18 | * v1.4.0 单表模式支持JPA和Mybatis-Plus,可自定义类名和文件名,支持Lombok和Swagger,添加代码配置方式,支持将MyBatis映射文件放于source目录下,调整代码生成策略(支持单表、一对多、多对一、多对多),可配置主键生成策略(数据库自增、UUID),可配置文件覆盖策略
19 | * v1.4.1 修复配置DO实体类别名时文件名错误的问题
20 |
21 | 详细 Release note :[GreedyStar/generator/Releases](https://github.com/GreedyStar/generator/releases)
22 |
23 | ### 具体请参考使用手册 : [Wiki-Generator](https://github.com/GreedyStar/generator/wiki)
24 |
25 | ## 致谢
26 |
27 | 感谢以下人员对本仓库提出的建议,我们期待本工具能够为更多的开发者提供便利。
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.greedystar
8 | generator
9 | 1.4.1
10 |
11 |
12 | org.sonatype.oss
13 | oss-parent
14 | 7
15 |
16 |
17 |
18 |
19 | The Apache Software License, Version 2.0
20 | http://www.apache.org/licenses/LICENSE-2.0.txt
21 | repo
22 |
23 |
24 |
25 | master
26 | git@github.com:GreedyStar/generator.git
27 | scm:git:git@github.com:GreedyStar/generator.git
28 | scm:git:git@github.com:GreedyStar/generator.git
29 |
30 |
31 |
32 | GreedyStar
33 | greedystar@163.com
34 | GreedyStar
35 |
36 |
37 |
38 |
39 | UTF-8
40 | 1.8
41 | 1.8
42 |
43 |
44 |
45 |
46 | org.freemarker
47 | freemarker
48 | 2.3.23
49 |
50 |
51 |
52 | org.yaml
53 | snakeyaml
54 | 1.19
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/application/Main.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.application;
2 |
3 | import com.greedystar.generator.invoker.Many2ManyInvoker;
4 | import com.greedystar.generator.invoker.Many2OneInvoker;
5 | import com.greedystar.generator.invoker.One2ManyInvoker;
6 | import com.greedystar.generator.invoker.SingleInvoker;
7 | import com.greedystar.generator.invoker.base.Invoker;
8 |
9 | /**
10 | * @author GreedyStar
11 | * @since 2018/9/5
12 | */
13 | public class Main {
14 |
15 | public static void main(String[] args) {
16 |
17 | }
18 |
19 | public static void many2many() {
20 | Invoker invoker = new Many2ManyInvoker.Builder()
21 | .setTableName("user")
22 | .setClassName("User")
23 | .setParentTableName("role")
24 | .setParentClassName("Role")
25 | .setRelationTableName("user_role")
26 | .setForeignKey("user_id")
27 | .setParentForeignKey("role_id")
28 | .build();
29 | invoker.execute();
30 | }
31 |
32 | public static void many2one() {
33 | Invoker one2many = new Many2OneInvoker.Builder()
34 | .setTableName("user")
35 | .setClassName("User")
36 | .setParentTableName("office")
37 | .setParentClassName("Office")
38 | .setForeignKey("office_id")
39 | .build();
40 | one2many.execute();
41 | }
42 |
43 | public static void one2many() {
44 | Invoker invoker = new One2ManyInvoker.Builder()
45 | .setTableName("user")
46 | .setClassName("User")
47 | .setParentTableName("article")
48 | .setParentClassName("Article")
49 | .setParentForeignKey("user_id")
50 | .build();
51 | invoker.execute();
52 | }
53 |
54 | public static void single() {
55 | Invoker invoker = new SingleInvoker.Builder()
56 | .setTableName("user")
57 | .setClassName("User")
58 | .build();
59 | invoker.execute();
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/convertor/DefaultConvertor.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.convertor;
2 |
3 | import java.sql.JDBCType;
4 |
5 | /**
6 | * @author GreedyStar
7 | * @since 2019/6/2
8 | */
9 | public class DefaultConvertor implements TypeConvertor {
10 |
11 | /**
12 | * 将JDBC类型转换为Java类型
13 | *
14 | * @param type JDBC类型名
15 | */
16 | @Override
17 | public String convertType(JDBCType type) {
18 | StringBuilder sb = new StringBuilder();
19 | switch (type) {
20 | case BIT:
21 | case BOOLEAN:
22 | sb.append("Boolean");
23 | break;
24 | case TINYINT:
25 | case SMALLINT:
26 | case INTEGER:
27 | sb.append("Integer");
28 | break;
29 | case BIGINT:
30 | sb.append("Long");
31 | break;
32 | case REAL:
33 | sb.append("Float");
34 | break;
35 | case FLOAT:
36 | case DOUBLE:
37 | sb.append("Double");
38 | break;
39 | case DECIMAL:
40 | case NUMERIC:
41 | sb.append("BigDecimal");
42 | break;
43 | case VARCHAR:
44 | case CHAR:
45 | case NCHAR:
46 | case NVARCHAR:
47 | case LONGVARCHAR:
48 | case LONGNVARCHAR:
49 | sb.append("String");
50 | break;
51 | case DATE:
52 | case TIME:
53 | case TIMESTAMP:
54 | sb.append("Date");
55 | break;
56 | case CLOB:
57 | case NCLOB:
58 | case BLOB:
59 | case BINARY:
60 | case VARBINARY:
61 | case LONGVARBINARY:
62 | sb.append("byte[]");
63 | break;
64 | default:
65 | sb.append("Object");
66 |
67 | }
68 | return sb.toString();
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/convertor/TypeConvertor.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.convertor;
2 |
3 | import java.sql.JDBCType;
4 |
5 | /**
6 | * @author GreedyStar
7 | * @since 2019/6/2
8 | */
9 | public interface TypeConvertor {
10 |
11 | /**
12 | * 将JDBC类型转换为Java类型
13 | *
14 | * @param type JDBC类型名
15 | * @return Java类型名
16 | */
17 | String convertType(JDBCType type);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/db/ConnectionUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.db;
2 |
3 |
4 | import com.greedystar.generator.entity.ColumnInfo;
5 | import com.greedystar.generator.utils.ConfigUtil;
6 | import com.greedystar.generator.utils.StringUtil;
7 |
8 | import java.sql.*;
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.List;
12 | import java.util.Properties;
13 |
14 | /**
15 | * 数据库连接工具类
16 | *
17 | * @author GreedyStar
18 | * @since 2018/4/19
19 | */
20 | public class ConnectionUtil {
21 | /**
22 | * 数据库连接
23 | */
24 | private Connection connection;
25 |
26 | /**
27 | * 初始化数据库连接
28 | *
29 | * @return 连接是否建立成功
30 | */
31 | public boolean initConnection() {
32 | try {
33 | Class.forName(DataBaseFactory.getDriver(ConfigUtil.getConfiguration().getDb().getUrl()));
34 | String url = ConfigUtil.getConfiguration().getDb().getUrl();
35 | String username = ConfigUtil.getConfiguration().getDb().getUsername();
36 | String password = ConfigUtil.getConfiguration().getDb().getPassword();
37 | Properties properties = new Properties();
38 | properties.put("user", username);
39 | properties.put("password", password == null ? "" : password);
40 | properties.setProperty("remarks", "true");
41 | properties.setProperty("useInformationSchema", "true");
42 | properties.setProperty("nullCatalogMeansCurrent", "true");
43 | connection = DriverManager.getConnection(url, properties);
44 | return true;
45 | } catch (ClassNotFoundException e) {
46 | e.printStackTrace();
47 | } catch (SQLException e) {
48 | e.printStackTrace();
49 | }
50 | return false;
51 | }
52 |
53 | /**
54 | * 获取表结构数据
55 | *
56 | * @param tableName 表名
57 | * @return 包含表结构数据的列表
58 | * @throws Exception Exception
59 | */
60 | public List getMetaData(String tableName) throws Exception {
61 | if (!initConnection()) {
62 | throw new Exception("Failed to connect to database at url:" + ConfigUtil.getConfiguration().getDb().getUrl());
63 | }
64 | // 获取主键
65 | String primaryKey = getPrimaryKey(tableName);
66 | // 获取表注释
67 | String tableRemark = getTableRemark(tableName);
68 | // 获取列信息
69 | List columnInfos = getColumnInfos(tableName, primaryKey, tableRemark);
70 | closeConnection();
71 | return columnInfos;
72 | }
73 |
74 | /**
75 | * 获取主键
76 | *
77 | * @param tableName 表名
78 | * @return 主键名称
79 | * @throws SQLException SQLException
80 | */
81 | private String getPrimaryKey(String tableName) throws SQLException {
82 | // 获取主键
83 | ResultSet keyResultSet = connection.getMetaData().getPrimaryKeys(DataBaseFactory.getCatalog(connection),
84 | DataBaseFactory.getSchema(connection), tableName);
85 | String primaryKey = null;
86 | if (keyResultSet.next()) {
87 | primaryKey = keyResultSet.getObject(4).toString();
88 | }
89 | keyResultSet.close();
90 | return primaryKey;
91 | }
92 |
93 | /**
94 | * 获取表注释
95 | *
96 | * @param tableName 表名
97 | * @return 表注释
98 | * @throws SQLException SQLException
99 | */
100 | private String getTableRemark(String tableName) throws SQLException {
101 | // 获取表注释
102 | String tableRemark = null;
103 | if (connection.getMetaData().getURL().contains("sqlserver")) { // SQLServer
104 | tableRemark = parseSqlServerTableRemarks(tableName);
105 | } else { // Oracle & MySQL
106 | ResultSet tableResultSet = connection.getMetaData().getTables(DataBaseFactory.getCatalog(connection),
107 | DataBaseFactory.getSchema(connection), tableName, new String[]{"TABLE"});
108 | if (tableResultSet.next()) {
109 | tableRemark = StringUtil.isEmpty(tableResultSet.getString("REMARKS")) ?
110 | "Unknown Table" : tableResultSet.getString("REMARKS");
111 | }
112 | tableResultSet.close();
113 | }
114 | return tableRemark;
115 | }
116 |
117 | /**
118 | * 获取列信息
119 | *
120 | * @param tableName 表名
121 | * @param primaryKey 主键列名
122 | * @param tableRemark 表注释
123 | * @return 列信息
124 | * @throws Exception Exception
125 | */
126 | private List getColumnInfos(String tableName, String primaryKey, String tableRemark) throws Exception {
127 | // 获取列信息
128 | List columnInfos = new ArrayList<>();
129 | ResultSet columnResultSet = connection.getMetaData().getColumns(DataBaseFactory.getCatalog(connection),
130 | DataBaseFactory.getSchema(connection), tableName, "%");
131 | while (columnResultSet.next()) {
132 | boolean isPrimaryKey;
133 | if (columnResultSet.getString("COLUMN_NAME").equals(primaryKey)) {
134 | isPrimaryKey = true;
135 | } else {
136 | isPrimaryKey = false;
137 | }
138 | ColumnInfo info = new ColumnInfo(columnResultSet.getString("COLUMN_NAME"), columnResultSet.getInt("DATA_TYPE"),
139 | StringUtil.isEmpty(columnResultSet.getString("REMARKS")) ? "Unknown" : columnResultSet.getString("REMARKS"),
140 | tableRemark, isPrimaryKey);
141 | columnInfos.add(info);
142 | }
143 | columnResultSet.close();
144 | if (columnInfos.size() == 0) {
145 | closeConnection();
146 | throw new Exception("Can not find column information from table:" + tableName);
147 | }
148 | // SQLServer需要单独处理列REMARKS
149 | if (connection.getMetaData().getURL().contains("sqlserver")) {
150 | parseSqlServerColumnRemarks(tableName, columnInfos);
151 | }
152 | return columnInfos;
153 | }
154 |
155 | /**
156 | * 主动查询SqlServer指定表的注释
157 | *
158 | * @param tableName 表名
159 | * @return 表注释
160 | * @throws SQLException SQLException
161 | */
162 | private String parseSqlServerTableRemarks(String tableName) throws SQLException {
163 | String tableRemarks = null;
164 | String sql = "SELECT CAST(ISNULL(p.value, '') AS nvarchar(25)) AS REMARKS FROM sys.tables t " +
165 | "LEFT JOIN sys.extended_properties p ON p.major_id=t.object_id AND p.minor_id=0 AND p.class=1 " +
166 | "WHERE t.name = ?";
167 | PreparedStatement preparedStatement = connection.prepareStatement(sql);
168 | preparedStatement.setString(1, tableName);
169 | ResultSet resultSet = preparedStatement.executeQuery();
170 | while (resultSet.next()) {
171 | tableRemarks = StringUtil.isEmpty(resultSet.getString("REMARKS")) ? "Unknown Table" : resultSet.getString("REMARKS");
172 | }
173 | resultSet.close();
174 | preparedStatement.close();
175 | return tableRemarks;
176 | }
177 |
178 | /**
179 | * 主动查询SqlServer指定表的数据列的注释
180 | *
181 | * @param tableName 表名
182 | * @throws SQLException SQLException
183 | */
184 | private void parseSqlServerColumnRemarks(String tableName, List columnInfos) throws SQLException {
185 | HashMap map = new HashMap<>();
186 | String sql = "SELECT c.name AS COLUMN_NAME, CAST(ISNULL(p.value, '') AS nvarchar(25)) AS REMARKS " +
187 | "FROM sys.tables t " +
188 | "INNER JOIN sys.columns c ON c.object_id = t.object_id " +
189 | "LEFT JOIN sys.extended_properties p ON p.major_id = c.object_id AND p.minor_id = c.column_id " +
190 | "WHERE t.name = ?";
191 | PreparedStatement preparedStatement = connection.prepareStatement(sql);
192 | preparedStatement.setString(1, tableName);
193 | ResultSet resultSet = preparedStatement.executeQuery();
194 | while (resultSet.next()) {
195 | map.put(resultSet.getString("COLUMN_NAME"), StringUtil.isEmpty(resultSet.getString("REMARKS")) ?
196 | "Unknown" : resultSet.getString("REMARKS"));
197 | }
198 | for (ColumnInfo columnInfo : columnInfos) {
199 | columnInfo.setRemarks(map.get(columnInfo.getColumnName()));
200 | }
201 | resultSet.close();
202 | preparedStatement.close();
203 | }
204 |
205 | /**
206 | * 关闭数据库连接
207 | * @throws SQLException SQLException
208 | */
209 | public void closeConnection() throws SQLException {
210 | if (!connection.isClosed()) {
211 | connection.close();
212 | }
213 | }
214 |
215 | }
216 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/db/DataBaseFactory.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.db;
2 |
3 | import java.sql.Connection;
4 | import java.sql.SQLException;
5 |
6 | /**
7 | * 数据库驱动工厂类
8 | *
9 | * @author GreedyStar
10 | * @since 2018-10-24
11 | */
12 | public class DataBaseFactory {
13 | private final static String DRIVER_MYSQL_5 = "com.mysql.jdbc.Driver";
14 | private final static String DRIVER_MYSQL_UPER = "com.mysql.cj.jdbc.Driver";
15 | private final static String DRIVER_ORACLE = "oracle.jdbc.driver.OracleDriver";
16 | private final static String DRIVER_SQLSERVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
17 |
18 | /**
19 | * 根据数据库连接url获取数据库驱动
20 | *
21 | * @param url 数据库url
22 | * @return 驱动类名
23 | */
24 | public static String getDriver(String url) {
25 | if (url.contains("mysql")) {
26 | if (url.contains("serverTimezone")) {
27 | return DRIVER_MYSQL_UPER;
28 | } else {
29 | return DRIVER_MYSQL_5;
30 | }
31 | }
32 | if (url.contains("oracle")) {
33 | return DRIVER_ORACLE;
34 | }
35 | if (url.contains("sqlserver")) {
36 | return DRIVER_SQLSERVER;
37 | }
38 | return null;
39 | }
40 |
41 | /**
42 | * 获取catalog
43 | *
44 | * @param connection 数据库连接
45 | * @return catalog
46 | * @throws SQLException SQLException
47 | */
48 | public static String getCatalog(Connection connection) throws SQLException {
49 | String url = connection.getMetaData().getURL();
50 | if (url.contains("mysql")) {
51 | return null;
52 | } else if (url.contains("oracle")) {
53 | return null;
54 | } else if (url.contains("sqlserver")) {
55 | return url.substring(url.lastIndexOf("=") + 1);
56 | }
57 | return null;
58 | }
59 |
60 | /**
61 | * 获取schema
62 | *
63 | * @param connection 数据库连接
64 | * @return schema
65 | * @throws SQLException SQLException
66 | */
67 | public static String getSchema(Connection connection) throws SQLException {
68 | String url = connection.getMetaData().getURL();
69 | if (url.contains("mysql")) {
70 | if (url.contains("?")) {
71 | url = url.replace("jdbc:mysql://", "");
72 | return url.substring(url.indexOf("/") + 1, url.lastIndexOf("?"));
73 | } else {
74 | return url.substring(url.lastIndexOf("/") + 1);
75 | }
76 | } else if (url.contains("oracle")) {
77 | return connection.getMetaData().getUserName();
78 | } else if (url.contains("sqlserver")) {
79 | return connection.getSchema();
80 | }
81 | return null;
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/entity/ColumnInfo.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.entity;
2 |
3 | import com.greedystar.generator.utils.ConvertorUtil;
4 | import com.greedystar.generator.utils.StringUtil;
5 |
6 | import java.io.Serializable;
7 | import java.sql.JDBCType;
8 |
9 | /**
10 | * 数据列实体
11 | *
12 | * @author GreedyStar
13 | * @since 2018/4/19
14 | */
15 | public class ColumnInfo implements Serializable {
16 | /**
17 | * 列名
18 | */
19 | private String columnName;
20 | /**
21 | * 列名 -- 属性名
22 | */
23 | private String propertyName;
24 | /**
25 | * 数据列类型
26 | */
27 | private JDBCType columnType;
28 | /**
29 | * 数据列类型 -- Java类型
30 | */
31 | private String propertyType;
32 | /**
33 | * 列备注
34 | */
35 | private String remarks;
36 | /**
37 | * 表备注
38 | */
39 | private String tableRemarks;
40 | /**
41 | * 是否主键
42 | */
43 | private boolean isPrimaryKey;
44 |
45 | public ColumnInfo(String columnName, int columnType, String remarks, String tableRemarks, boolean isPrimaryKey) {
46 | this.columnName = columnName;
47 | this.propertyName = StringUtil.columnName2PropertyName(columnName);
48 | this.columnType = JDBCType.valueOf(columnType);
49 | this.propertyType = ConvertorUtil.parseTypeFormSqlType(JDBCType.valueOf(columnType));
50 | this.remarks = remarks;
51 | this.tableRemarks = tableRemarks;
52 | this.isPrimaryKey = isPrimaryKey;
53 | }
54 |
55 | public String getColumnName() {
56 | return columnName;
57 | }
58 |
59 | public void setColumnName(String columnName) {
60 | this.columnName = columnName;
61 | }
62 |
63 | public String getPropertyName() {
64 | return propertyName;
65 | }
66 |
67 | public void setPropertyName(String propertyName) {
68 | this.propertyName = propertyName;
69 | }
70 |
71 | public JDBCType getColumnType() {
72 | return columnType;
73 | }
74 |
75 | public void setColumnType(JDBCType columnType) {
76 | this.columnType = columnType;
77 | }
78 |
79 | public String getPropertyType() {
80 | return propertyType;
81 | }
82 |
83 | public void setPropertyType(String propertyType) {
84 | this.propertyType = propertyType;
85 | }
86 |
87 | public String getRemarks() {
88 | return remarks;
89 | }
90 |
91 | public void setRemarks(String remarks) {
92 | this.remarks = remarks;
93 | }
94 |
95 | public String getTableRemarks() {
96 | return tableRemarks;
97 | }
98 |
99 | public void setTableRemarks(String tableRemarks) {
100 | this.tableRemarks = tableRemarks;
101 | }
102 |
103 | public boolean isPrimaryKey() {
104 | return isPrimaryKey;
105 | }
106 |
107 | public void setPrimaryKey(boolean primaryKey) {
108 | isPrimaryKey = primaryKey;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/entity/Configuration.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Generator 配置类
7 | *
8 | * @author GreedyStar
9 | * @since 2018/9/7
10 | */
11 | public class Configuration implements Serializable {
12 | /**
13 | * 代码作者
14 | */
15 | private String author;
16 | /**
17 | * 顶级包名
18 | */
19 | private String packageName;
20 | /**
21 | * 类型转换器全限定类名
22 | */
23 | private String convertor;
24 | /**
25 | * 启用lombok
26 | */
27 | private boolean lombokEnable;
28 | /**
29 | * 是否将mybatis的xml映射文件放在源文件目录下
30 | */
31 | private boolean mapperUnderSource;
32 | /**
33 | * 启用swagger
34 | */
35 | private boolean swaggerEnable;
36 | /**
37 | * mybatis-plus模式
38 | */
39 | private boolean mybatisPlusEnable;
40 | /**
41 | * jpa模式
42 | */
43 | private boolean jpaEnable;
44 | /**
45 | * 文件覆盖
46 | */
47 | private boolean fileOverride;
48 | /**
49 | * id策略(auto:数据库自增,uuid:生成uuid)
50 | */
51 | private IdStrategy idStrategy;
52 | /**
53 | * 代码生成路径
54 | */
55 | private Path path;
56 | /**
57 | * 数据库配置
58 | */
59 | private Db db;
60 | /**
61 | * 代码文件后缀
62 | */
63 | private Name name;
64 |
65 | public String getAuthor() {
66 | return author;
67 | }
68 |
69 | public void setAuthor(String author) {
70 | this.author = author;
71 | }
72 |
73 | public String getPackageName() {
74 | return packageName;
75 | }
76 |
77 | public void setPackageName(String packageName) {
78 | this.packageName = packageName;
79 | }
80 |
81 | public String getConvertor() {
82 | return convertor;
83 | }
84 |
85 | public void setConvertor(String convertor) {
86 | this.convertor = convertor;
87 | }
88 |
89 | public boolean isLombokEnable() {
90 | return lombokEnable;
91 | }
92 |
93 | public void setLombokEnable(boolean lombokEnable) {
94 | this.lombokEnable = lombokEnable;
95 | }
96 |
97 | public boolean isMapperUnderSource() {
98 | return mapperUnderSource;
99 | }
100 |
101 | public void setMapperUnderSource(boolean mapperUnderSource) {
102 | this.mapperUnderSource = mapperUnderSource;
103 | }
104 |
105 | public boolean isSwaggerEnable() {
106 | return swaggerEnable;
107 | }
108 |
109 | public void setSwaggerEnable(boolean swaggerEnable) {
110 | this.swaggerEnable = swaggerEnable;
111 | }
112 |
113 | public boolean isMybatisPlusEnable() {
114 | return mybatisPlusEnable;
115 | }
116 |
117 | public void setMybatisPlusEnable(boolean mybatisPlusEnable) {
118 | this.mybatisPlusEnable = mybatisPlusEnable;
119 | }
120 |
121 | public boolean isJpaEnable() {
122 | return jpaEnable;
123 | }
124 |
125 | public void setJpaEnable(boolean jpaEnable) {
126 | this.jpaEnable = jpaEnable;
127 | }
128 |
129 | public boolean isFileOverride() {
130 | return fileOverride;
131 | }
132 |
133 | public void setFileOverride(boolean fileOverride) {
134 | this.fileOverride = fileOverride;
135 | }
136 |
137 | public IdStrategy getIdStrategy() {
138 | return idStrategy;
139 | }
140 |
141 | public void setIdStrategy(IdStrategy idStrategy) {
142 | this.idStrategy = idStrategy;
143 | }
144 |
145 | public Path getPath() {
146 | return path;
147 | }
148 |
149 | public void setPath(Path path) {
150 | this.path = path;
151 | }
152 |
153 | public Db getDb() {
154 | return db;
155 | }
156 |
157 | public void setDb(Db db) {
158 | this.db = db;
159 | }
160 |
161 | public Name getName() {
162 | return name;
163 | }
164 |
165 | public void setName(Name name) {
166 | this.name = name;
167 | }
168 |
169 | /**
170 | * 数据库配置
171 | */
172 | public static class Db {
173 | /**
174 | * 数据库URL
175 | */
176 | private String url;
177 | /**
178 | * 数据库用户名
179 | */
180 | private String username;
181 | /**
182 | * 数据库密码
183 | */
184 | private String password;
185 |
186 | public Db() {
187 | }
188 |
189 | public Db(String url, String username, String password) {
190 | this.url = url;
191 | this.username = username;
192 | this.password = password;
193 | }
194 |
195 | public String getUrl() {
196 | return url;
197 | }
198 |
199 | public void setUrl(String url) {
200 | this.url = url;
201 | }
202 |
203 | public String getUsername() {
204 | return username;
205 | }
206 |
207 | public void setUsername(String username) {
208 | this.username = username;
209 | }
210 |
211 | public String getPassword() {
212 | return password;
213 | }
214 |
215 | public void setPassword(String password) {
216 | this.password = password;
217 | }
218 | }
219 |
220 | /**
221 | * 代码路径配置
222 | */
223 | public static class Path {
224 | /**
225 | * Controller代码包路径
226 | */
227 | private String controller = "";
228 | /**
229 | * Service或ServiceImpl代码包路径
230 | */
231 | private String service = "";
232 | /**
233 | * Service接口代码包路径
234 | */
235 | private String interf = "";
236 | /**
237 | * Dao代码包路径
238 | */
239 | private String dao = "";
240 | /**
241 | * Entity代码包路径
242 | */
243 | private String entity = "";
244 | /**
245 | * Mapper映射文件路径
246 | */
247 | private String mapper = "";
248 |
249 | public Path() {
250 | }
251 |
252 | public Path(String controller, String service, String interf, String dao, String entity, String mapper) {
253 | this.controller = controller;
254 | this.service = service;
255 | this.interf = interf;
256 | this.dao = dao;
257 | this.entity = entity;
258 | this.mapper = mapper;
259 | }
260 |
261 | public String getController() {
262 | return controller;
263 | }
264 |
265 | public void setController(String controller) {
266 | this.controller = controller;
267 | }
268 |
269 | public String getService() {
270 | return service;
271 | }
272 |
273 | public void setService(String service) {
274 | this.service = service;
275 | }
276 |
277 | public String getInterf() {
278 | return interf;
279 | }
280 |
281 | public void setInterf(String interf) {
282 | this.interf = interf;
283 | }
284 |
285 | public String getDao() {
286 | return dao;
287 | }
288 |
289 | public void setDao(String dao) {
290 | this.dao = dao;
291 | }
292 |
293 | public String getEntity() {
294 | return entity;
295 | }
296 |
297 | public void setEntity(String entity) {
298 | this.entity = entity;
299 | }
300 |
301 | public String getMapper() {
302 | return mapper;
303 | }
304 |
305 | public void setMapper(String mapper) {
306 | this.mapper = mapper;
307 | }
308 |
309 | }
310 |
311 | /**
312 | * 类名配置
313 | */
314 | public static class Name {
315 | /**
316 | * Controller类的类名,默认为 $sController
317 | */
318 | private String controller = Constant.PLACEHOLDER + "Controller";
319 | /**
320 | * Service类或ServiceImpl类的类名,默认为$sService或$sServiceImpl
321 | */
322 | private String service = Constant.PLACEHOLDER + "Service";
323 | /**
324 | * Service接口类的类名,默认为$sService
325 | */
326 | private String interf = Constant.PLACEHOLDER + "Service";
327 | /**
328 | * Dao类的类名,默认为$sDao
329 | */
330 | private String dao = Constant.PLACEHOLDER + "Dao";
331 | /**
332 | * Entity类的类名,默认为$s
333 | */
334 | private String entity = Constant.PLACEHOLDER;
335 | /**
336 | * Mapper映射文件的文件名,默认$sMapper
337 | */
338 | private String mapper = Constant.PLACEHOLDER + "Mapper";
339 |
340 | public Name() {
341 | }
342 |
343 | public Name(String controller, String service, String dao, String entity, String mapper) {
344 | this.controller = controller;
345 | this.service = service;
346 | this.dao = dao;
347 | this.entity = entity;
348 | this.mapper = mapper;
349 | }
350 |
351 | public String getController() {
352 | return controller;
353 | }
354 |
355 | public void setController(String controller) {
356 | this.controller = controller;
357 | }
358 |
359 | public String getService() {
360 | return service;
361 | }
362 |
363 | public void setService(String service) {
364 | this.service = service;
365 | }
366 |
367 | public String getInterf() {
368 | return interf;
369 | }
370 |
371 | public void setInterf(String interf) {
372 | this.interf = interf;
373 | }
374 |
375 | public String getDao() {
376 | return dao;
377 | }
378 |
379 | public void setDao(String dao) {
380 | this.dao = dao;
381 | }
382 |
383 | public String getEntity() {
384 | return entity;
385 | }
386 |
387 | public void setEntity(String entity) {
388 | this.entity = entity;
389 | }
390 |
391 | public String getMapper() {
392 | return mapper;
393 | }
394 |
395 | public void setMapper(String mapper) {
396 | this.mapper = mapper;
397 | }
398 |
399 | }
400 |
401 | }
402 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/entity/Constant.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.entity;
2 |
3 | /**
4 | * 常量
5 | *
6 | * @author GreedyStar
7 | * @since 2020/6/28
8 | */
9 | public class Constant {
10 | /**
11 | * 空格 * 4
12 | */
13 | public final static String SPACE_4 = " ";
14 | /**
15 | * 空格 * 8
16 | */
17 | public final static String SPACE_8 = " ";
18 | /**
19 | * 空格 * 12
20 | */
21 | public final static String SPACE_12 = " ";
22 | /**
23 | * 文件名占位符
24 | */
25 | public final static String PLACEHOLDER = "$s";
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/entity/IdStrategy.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.entity;
2 |
3 | /**
4 | * @author GreedyStar
5 | * @since 2020/10/15
6 | */
7 | public enum IdStrategy {
8 | AUTO,
9 | UUID;
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/entity/Mode.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.entity;
2 |
3 | /**
4 | * Entity任务模式
5 | *
6 | * @author GreedyStar
7 | * @since 2020/8/1
8 | */
9 | public enum Mode {
10 | /**
11 | * 主表模式
12 | */
13 | ENTITY_MAIN,
14 | /**
15 | * 父表模式
16 | */
17 | ENTITY_PARENT;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/Many2ManyInvoker.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker;
2 |
3 | import com.greedystar.generator.invoker.base.AbstractBuilder;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.utils.ConfigUtil;
6 | import com.greedystar.generator.utils.StringUtil;
7 |
8 | /**
9 | * @author GreedyStar
10 | * @since 2018/9/5
11 | */
12 | public class Many2ManyInvoker extends AbstractInvoker {
13 |
14 | private Many2ManyInvoker() {
15 |
16 | }
17 |
18 | @Override
19 | protected void queryMetaData() throws Exception {
20 | tableInfos = connectionUtil.getMetaData(tableName);
21 | parentTableInfos = connectionUtil.getMetaData(parentTableName);
22 | }
23 |
24 | @Override
25 | protected void initTasks() {
26 | taskQueue.initMany2ManyTasks(this);
27 | }
28 |
29 | public static class Builder extends AbstractBuilder {
30 |
31 | public Builder() {
32 | invoker = new Many2ManyInvoker();
33 | }
34 |
35 | public Builder setTableName(String tableName) {
36 | invoker.setTableName(tableName);
37 | return this;
38 | }
39 |
40 | public Builder setClassName(String className) {
41 | invoker.setClassName(className);
42 | return this;
43 | }
44 |
45 | public Builder setParentTableName(String parentTableName) {
46 | invoker.setParentTableName(parentTableName);
47 | return this;
48 | }
49 |
50 | public Builder setParentClassName(String parentClassName) {
51 | invoker.setParentClassName(parentClassName);
52 | return this;
53 | }
54 |
55 | public Builder setForeignKey(String foreignKey) {
56 | invoker.setForeignKey(foreignKey);
57 | return this;
58 | }
59 |
60 | public Builder setRelationTableName(String relationTableName) {
61 | invoker.setRelationalTableName(relationTableName);
62 | return this;
63 | }
64 |
65 | public Builder setParentForeignKey(String parentForeignKey) {
66 | invoker.setParentForeignKey(parentForeignKey);
67 | return this;
68 | }
69 |
70 | @Override
71 | public void checkBeforeBuild() throws Exception {
72 | if (ConfigUtil.getConfiguration().isMybatisPlusEnable() || ConfigUtil.getConfiguration().isJpaEnable()) {
73 | throw new Exception("JPA mode and Mybatis-Plus mode only supported in SingleInvoker.");
74 | }
75 | if (StringUtil.isEmpty(invoker.getTableName())) {
76 | throw new Exception("Table name can't be null.");
77 | }
78 | if (StringUtil.isEmpty(invoker.getParentTableName())) {
79 | throw new Exception("Parent table name can't be null.");
80 | }
81 | if (StringUtil.isEmpty(invoker.getRelationalTableName())) {
82 | throw new Exception("Relational table name can't be null.");
83 | }
84 | if (StringUtil.isEmpty(invoker.getForeignKey())) {
85 | throw new Exception("Foreign key can't be null.");
86 | }
87 | if (StringUtil.isEmpty(invoker.getParentForeignKey())) {
88 | throw new Exception("Parent foreign key can't be null.");
89 | }
90 | if (StringUtil.isEmpty(invoker.getClassName())) {
91 | invoker.setClassName(StringUtil.tableName2ClassName(invoker.getTableName()));
92 | }
93 | if (StringUtil.isEmpty(invoker.getParentClassName())) {
94 | invoker.setParentClassName(StringUtil.tableName2ClassName(invoker.getParentTableName()));
95 | }
96 | }
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/Many2OneInvoker.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker;
2 |
3 | import com.greedystar.generator.invoker.base.AbstractBuilder;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.utils.ConfigUtil;
6 | import com.greedystar.generator.utils.StringUtil;
7 |
8 | /**
9 | * @author GreedyStar
10 | * @since 2020/7/31
11 | */
12 | public class Many2OneInvoker extends AbstractInvoker {
13 |
14 | private Many2OneInvoker() {
15 |
16 | }
17 |
18 | @Override
19 | protected void queryMetaData() throws Exception {
20 | tableInfos = connectionUtil.getMetaData(tableName);
21 | parentTableInfos = connectionUtil.getMetaData(parentTableName);
22 | }
23 |
24 | @Override
25 | protected void initTasks() {
26 | taskQueue.initMany2OneTasks(this);
27 | }
28 |
29 | public static class Builder extends AbstractBuilder {
30 |
31 | public Builder() {
32 | invoker = new Many2OneInvoker();
33 | }
34 |
35 | public Builder setTableName(String tableName) {
36 | invoker.setTableName(tableName);
37 | return this;
38 | }
39 |
40 | public Builder setClassName(String className) {
41 | invoker.setClassName(className);
42 | return this;
43 | }
44 |
45 | public Builder setParentTableName(String parentTableName) {
46 | invoker.setParentTableName(parentTableName);
47 | return this;
48 | }
49 |
50 | public Builder setParentClassName(String parentClassName) {
51 | invoker.setParentClassName(parentClassName);
52 | return this;
53 | }
54 |
55 | public Builder setForeignKey(String foreignKey) {
56 | invoker.setForeignKey(foreignKey);
57 | return this;
58 | }
59 |
60 | @Override
61 | public void checkBeforeBuild() throws Exception {
62 | if (ConfigUtil.getConfiguration().isMybatisPlusEnable() || ConfigUtil.getConfiguration().isJpaEnable()) {
63 | throw new Exception("JPA mode and Mybatis-Plus mode only supported in SingleInvoker.");
64 | }
65 | if (StringUtil.isEmpty(invoker.getTableName())) {
66 | throw new Exception("Table name can't be null.");
67 | }
68 | if (StringUtil.isEmpty(invoker.getParentTableName())) {
69 | throw new Exception("Parent table name can't be null.");
70 | }
71 | if (StringUtil.isEmpty(invoker.getForeignKey())) {
72 | throw new Exception("Foreign key can't be null.");
73 | }
74 | if (StringUtil.isEmpty(invoker.getClassName())) {
75 | invoker.setClassName(StringUtil.tableName2ClassName(invoker.getTableName()));
76 | }
77 | if (StringUtil.isEmpty(invoker.getParentClassName())) {
78 | invoker.setParentClassName(StringUtil.tableName2ClassName(invoker.getParentTableName()));
79 | }
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/One2ManyInvoker.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker;
2 |
3 | import com.greedystar.generator.invoker.base.AbstractBuilder;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.utils.ConfigUtil;
6 | import com.greedystar.generator.utils.StringUtil;
7 |
8 | /**
9 | * @author GreedyStar
10 | * @since 2018/9/5
11 | */
12 | public class One2ManyInvoker extends AbstractInvoker {
13 |
14 | private One2ManyInvoker() {
15 |
16 | }
17 |
18 | @Override
19 | protected void queryMetaData() throws Exception {
20 | tableInfos = connectionUtil.getMetaData(tableName);
21 | parentTableInfos = connectionUtil.getMetaData(parentTableName);
22 | }
23 |
24 | @Override
25 | protected void initTasks() {
26 | taskQueue.initOne2ManyTasks(this);
27 | }
28 |
29 | public static class Builder extends AbstractBuilder {
30 |
31 | public Builder() {
32 | invoker = new One2ManyInvoker();
33 | }
34 |
35 | public Builder setTableName(String tableName) {
36 | invoker.setTableName(tableName);
37 | return this;
38 | }
39 |
40 | public Builder setClassName(String className) {
41 | invoker.setClassName(className);
42 | return this;
43 | }
44 |
45 | public Builder setParentTableName(String parentTableName) {
46 | invoker.setParentTableName(parentTableName);
47 | return this;
48 | }
49 |
50 | public Builder setParentClassName(String parentClassName) {
51 | invoker.setParentClassName(parentClassName);
52 | return this;
53 | }
54 |
55 | public Builder setParentForeignKey(String parentForeignKey) {
56 | invoker.setParentForeignKey(parentForeignKey);
57 | return this;
58 | }
59 |
60 | @Override
61 | public void checkBeforeBuild() throws Exception {
62 | if (ConfigUtil.getConfiguration().isMybatisPlusEnable() || ConfigUtil.getConfiguration().isJpaEnable()) {
63 | throw new Exception("JPA mode and Mybatis-Plus mode only supported in SingleInvoker.");
64 | }
65 | if (StringUtil.isEmpty(invoker.getTableName())) {
66 | throw new Exception("Table name can't be null.");
67 | }
68 | if (StringUtil.isEmpty(invoker.getParentTableName())) {
69 | throw new Exception("Parent table name can't be null.");
70 | }
71 | if (StringUtil.isEmpty(invoker.getParentForeignKey())) {
72 | throw new Exception("Parent foreign key can't be null.");
73 | }
74 | if (StringUtil.isEmpty(invoker.getClassName())) {
75 | invoker.setClassName(StringUtil.tableName2ClassName(invoker.getTableName()));
76 | }
77 | if (StringUtil.isEmpty(invoker.getParentClassName())) {
78 | invoker.setParentClassName(StringUtil.tableName2ClassName(invoker.getParentTableName()));
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/SingleInvoker.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker;
2 |
3 | import com.greedystar.generator.invoker.base.AbstractBuilder;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.utils.StringUtil;
6 |
7 | /**
8 | * @author GreedyStar
9 | * @since 2018/9/5
10 | */
11 | public class SingleInvoker extends AbstractInvoker {
12 |
13 | private SingleInvoker() {
14 |
15 | }
16 |
17 | @Override
18 | protected void queryMetaData() throws Exception {
19 | tableInfos = connectionUtil.getMetaData(tableName);
20 | }
21 |
22 | @Override
23 | protected void initTasks() {
24 | taskQueue.initSingleTasks(this);
25 | }
26 |
27 | public static class Builder extends AbstractBuilder {
28 |
29 | public Builder() {
30 | invoker = new SingleInvoker();
31 | }
32 |
33 | public Builder setTableName(String tableName) {
34 | invoker.setTableName(tableName);
35 | return this;
36 | }
37 |
38 | public Builder setClassName(String className) {
39 | invoker.setClassName(className);
40 | return this;
41 | }
42 |
43 | @Override
44 | public void checkBeforeBuild() throws Exception {
45 | if (StringUtil.isEmpty(invoker.getTableName())) {
46 | throw new Exception("Table name can't be null.");
47 | }
48 | if (StringUtil.isEmpty(invoker.getClassName())) {
49 | invoker.setClassName(StringUtil.tableName2ClassName(invoker.getTableName()));
50 | }
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/base/AbstractBuilder.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker.base;
2 |
3 | /**
4 | * @author GreedyStar
5 | * @since 2018/9/5
6 | */
7 | public abstract class AbstractBuilder {
8 | protected AbstractInvoker invoker;
9 |
10 | public Invoker build() {
11 | if (!isParamtersValid()) {
12 | return null;
13 | }
14 | return invoker;
15 | }
16 |
17 | private boolean isParamtersValid() {
18 | try {
19 | checkBeforeBuild();
20 | } catch (Exception e) {
21 | e.printStackTrace();
22 | return false;
23 | }
24 | return true;
25 | }
26 |
27 | /**
28 | * 在创建invoker对象前进行一些检查,由子类去实现
29 | *
30 | * @throws Exception 检查失败则抛出异常
31 | */
32 | protected abstract void checkBeforeBuild() throws Exception;
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/base/AbstractInvoker.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker.base;
2 |
3 | import com.greedystar.generator.db.ConnectionUtil;
4 | import com.greedystar.generator.entity.ColumnInfo;
5 | import com.greedystar.generator.task.base.AbstractTask;
6 | import com.greedystar.generator.utils.TaskQueue;
7 | import freemarker.template.TemplateException;
8 |
9 | import java.io.IOException;
10 | import java.util.List;
11 | import java.util.concurrent.ExecutorService;
12 | import java.util.concurrent.Executors;
13 |
14 | /**
15 | * @author GreedyStar
16 | * @since 2018/9/5
17 | */
18 | public abstract class AbstractInvoker implements Invoker {
19 | /**
20 | * 主表名
21 | */
22 | protected String tableName;
23 | /**
24 | * 主类名
25 | */
26 | protected String className;
27 | /**
28 | * 父表名
29 | */
30 | protected String parentTableName;
31 | /**
32 | * 父类名
33 | */
34 | protected String parentClassName;
35 | /**
36 | * 外键列名
37 | */
38 | protected String foreignKey;
39 | /**
40 | * 关系表名
41 | */
42 | protected String relationalTableName;
43 | /**
44 | * 父表外键列名
45 | */
46 | protected String parentForeignKey;
47 | /**
48 | * 主表元数据
49 | */
50 | protected List tableInfos;
51 | /**
52 | * 父表元数据
53 | */
54 | protected List parentTableInfos;
55 | /**
56 | * 数据库连接工具
57 | */
58 | protected ConnectionUtil connectionUtil = new ConnectionUtil();
59 | /**
60 | * 任务队列
61 | */
62 | protected TaskQueue taskQueue = new TaskQueue();
63 | /**
64 | * 线程池
65 | */
66 | private ExecutorService executorPool = Executors.newFixedThreadPool(6);
67 |
68 | /**
69 | * 获取表元数据,模板方法,由子类实现
70 | *
71 | * @throws Exception 获取元数据失败则抛出异常
72 | */
73 | protected abstract void queryMetaData() throws Exception;
74 |
75 | /**
76 | * 初始化代码生成任务,模板方法,由子类实现
77 | */
78 | protected abstract void initTasks();
79 |
80 | /**
81 | * 开始生成代码
82 | */
83 | @Override
84 | public void execute() {
85 | try {
86 | queryMetaData();
87 | initTasks();
88 | while (!taskQueue.isEmpty()) {
89 | AbstractTask task = taskQueue.poll();
90 | executorPool.execute(() -> {
91 | try {
92 | task.run();
93 | } catch (IOException e) {
94 | e.printStackTrace();
95 | } catch (TemplateException e) {
96 | e.printStackTrace();
97 | }
98 | });
99 | }
100 | executorPool.shutdown();
101 | } catch (Exception e) {
102 | e.printStackTrace();
103 | }
104 | }
105 |
106 | public void setTableName(String tableName) {
107 | this.tableName = tableName;
108 | }
109 |
110 | public void setClassName(String className) {
111 | this.className = className;
112 | }
113 |
114 | public void setParentTableName(String parentTableName) {
115 | this.parentTableName = parentTableName;
116 | }
117 |
118 | public void setParentClassName(String parentClassName) {
119 | this.parentClassName = parentClassName;
120 | }
121 |
122 | public void setForeignKey(String foreignKey) {
123 | this.foreignKey = foreignKey;
124 | }
125 |
126 | public void setRelationalTableName(String relationalTableName) {
127 | this.relationalTableName = relationalTableName;
128 | }
129 |
130 | public void setParentForeignKey(String parentForeignKey) {
131 | this.parentForeignKey = parentForeignKey;
132 | }
133 |
134 | public String getTableName() {
135 | return tableName;
136 | }
137 |
138 | public String getClassName() {
139 | return className;
140 | }
141 |
142 | public String getParentTableName() {
143 | return parentTableName;
144 | }
145 |
146 | public String getParentClassName() {
147 | return parentClassName;
148 | }
149 |
150 | public String getForeignKey() {
151 | return foreignKey;
152 | }
153 |
154 | public String getRelationalTableName() {
155 | return relationalTableName;
156 | }
157 |
158 | public String getParentForeignKey() {
159 | return parentForeignKey;
160 | }
161 |
162 | public List getTableInfos() {
163 | return tableInfos;
164 | }
165 |
166 | public void setTableInfos(List tableInfos) {
167 | this.tableInfos = tableInfos;
168 | }
169 |
170 | public List getParentTableInfos() {
171 | return parentTableInfos;
172 | }
173 |
174 | public void setParentTableInfos(List parentTableInfos) {
175 | this.parentTableInfos = parentTableInfos;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/invoker/base/Invoker.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.invoker.base;
2 |
3 | /**
4 | * @author GreedyStar
5 | * @since 2018-09-10
6 | */
7 | public interface Invoker {
8 |
9 | public void execute();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/ControllerTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task;
2 |
3 | import com.greedystar.generator.entity.ColumnInfo;
4 | import com.greedystar.generator.entity.Constant;
5 | import com.greedystar.generator.invoker.base.AbstractInvoker;
6 | import com.greedystar.generator.task.base.AbstractTask;
7 | import com.greedystar.generator.utils.*;
8 | import freemarker.template.TemplateException;
9 |
10 | import java.io.IOException;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | /**
16 | * @author GreedyStar
17 | * @since 2018/4/20
18 | */
19 | public class ControllerTask extends AbstractTask {
20 |
21 | public ControllerTask(AbstractInvoker invoker) {
22 | this.invoker = invoker;
23 | }
24 |
25 | @Override
26 | public void run() throws IOException, TemplateException {
27 | // 构造Controller填充数据
28 | Map controllerData = new HashMap<>();
29 | controllerData.put("Configuration", ConfigUtil.getConfiguration());
30 | String serviceClassName;
31 | String serviceImport;
32 | if (StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getInterf())) {
33 | serviceClassName = ConfigUtil.getConfiguration().getName().getService().replace(Constant.PLACEHOLDER, invoker.getClassName());
34 | serviceImport = String.format("import %s.%s.%s;", ConfigUtil.getConfiguration().getPackageName(),
35 | ConfigUtil.getConfiguration().getPath().getService(), serviceClassName);
36 | } else {
37 | serviceClassName = ConfigUtil.getConfiguration().getName().getInterf().replace(Constant.PLACEHOLDER, invoker.getClassName());
38 | serviceImport = String.format("import %s.%s.%s;", ConfigUtil.getConfiguration().getPackageName(),
39 | ConfigUtil.getConfiguration().getPath().getInterf(), serviceClassName);
40 | }
41 | controllerData.put("ServiceImport", serviceImport);
42 | controllerData.put("ServiceClassName", serviceClassName);
43 | controllerData.put("ServiceEntityName", StringUtil.firstToLowerCase(serviceClassName));
44 | controllerData.put("ControllerClassName", ConfigUtil.getConfiguration().getName().getController()
45 | .replace(Constant.PLACEHOLDER, invoker.getClassName()));
46 | controllerData.put("ClassName", ConfigUtil.getConfiguration().getName().getEntity()
47 | .replace(Constant.PLACEHOLDER, invoker.getClassName()));
48 | controllerData.put("EntityName", StringUtil.firstToLowerCase(invoker.getClassName()));
49 | controllerData.put("pkType", getPrimaryKeyType(invoker.getTableInfos()));
50 | String filePath = FileUtil.getSourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPackageName()) +
51 | StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getController());
52 | String fileName = ConfigUtil.getConfiguration().getName().getController().replace(Constant.PLACEHOLDER, invoker.getClassName()) + ".java";
53 | // 生成Controller文件
54 | FileUtil.generateToJava(FreemarkerConfigUtil.TYPE_CONTROLLER, controllerData, filePath, fileName);
55 | }
56 |
57 | /**
58 | * 获取主键列对应的属性类型
59 | *
60 | * @param columnInfos
61 | * @return
62 | */
63 | private String getPrimaryKeyType(List columnInfos) {
64 | if (!ConfigUtil.getConfiguration().isJpaEnable()) {
65 | return "Serializable";
66 | }
67 | for (ColumnInfo info : columnInfos) {
68 | if (info.isPrimaryKey()) {
69 | return info.getPropertyType();
70 | }
71 | }
72 | return "Serializable";
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/DaoTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task;
2 |
3 | import com.greedystar.generator.entity.Constant;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.task.base.AbstractTask;
6 | import com.greedystar.generator.utils.*;
7 | import freemarker.template.TemplateException;
8 |
9 | import java.io.IOException;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | /**
14 | * @author GreedyStar
15 | * @since 2018/4/20
16 | */
17 | public class DaoTask extends AbstractTask {
18 |
19 | public DaoTask(AbstractInvoker invoker) {
20 | this.invoker = invoker;
21 | }
22 |
23 | @Override
24 | public void run() throws IOException, TemplateException {
25 | // 构造Dao填充数据
26 | Map daoData = new HashMap<>();
27 | daoData.put("Configuration", ConfigUtil.getConfiguration());
28 | daoData.put("ClassName", ConfigUtil.getConfiguration().getName().getEntity().replace(Constant.PLACEHOLDER, invoker.getClassName()));
29 | daoData.put("EntityName", StringUtil.firstToLowerCase(invoker.getClassName()));
30 | daoData.put("DaoClassName", ConfigUtil.getConfiguration().getName().getDao().replace(Constant.PLACEHOLDER, invoker.getClassName()));
31 | String filePath = FileUtil.getSourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPackageName())
32 | + StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getDao());
33 | String fileName = ConfigUtil.getConfiguration().getName().getDao().replace(Constant.PLACEHOLDER, invoker.getClassName()) + ".java";
34 | // 生成dao文件
35 | FileUtil.generateToJava(FreemarkerConfigUtil.TYPE_DAO, daoData, filePath, fileName);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/EntityTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task;
2 |
3 | import com.greedystar.generator.entity.ColumnInfo;
4 | import com.greedystar.generator.entity.Constant;
5 | import com.greedystar.generator.entity.IdStrategy;
6 | import com.greedystar.generator.entity.Mode;
7 | import com.greedystar.generator.invoker.base.AbstractInvoker;
8 | import com.greedystar.generator.task.base.AbstractTask;
9 | import com.greedystar.generator.utils.*;
10 | import freemarker.template.TemplateException;
11 |
12 | import java.io.IOException;
13 | import java.util.HashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | /**
18 | * @author GreedyStar
19 | * @since 2018/4/20
20 | */
21 | public class EntityTask extends AbstractTask {
22 | /**
23 | * 业务表元数据
24 | */
25 | private List tableInfos;
26 | /**
27 | * 任务模式
28 | */
29 | private Mode mode;
30 |
31 | public EntityTask(Mode mode, AbstractInvoker invoker) {
32 | this.mode = mode;
33 | this.invoker = invoker;
34 | if (Mode.ENTITY_MAIN.equals(mode)) {
35 | this.tableInfos = invoker.getTableInfos();
36 | } else if (Mode.ENTITY_PARENT.equals(mode)) {
37 | this.tableInfos = invoker.getParentTableInfos();
38 | }
39 | }
40 |
41 | @Override
42 | public void run() throws IOException, TemplateException {
43 | // 构造Entity填充数据
44 | String className = null;
45 | String remarks = null;
46 | if (Mode.ENTITY_MAIN.equals(mode)) {
47 | className = ConfigUtil.getConfiguration().getName().getEntity().replace(Constant.PLACEHOLDER, invoker.getClassName());
48 | remarks = invoker.getTableInfos().get(0).getTableRemarks();
49 | } else if (Mode.ENTITY_PARENT.equals(mode)) {
50 | className = ConfigUtil.getConfiguration().getName().getEntity().replace(Constant.PLACEHOLDER, invoker.getParentClassName());
51 | remarks = invoker.getParentTableInfos().get(0).getTableRemarks();
52 | }
53 | Map entityData = new HashMap<>();
54 | entityData.put("Configuration", ConfigUtil.getConfiguration());
55 | entityData.put("TableName", invoker.getTableName());
56 | entityData.put("ClassName", className);
57 | entityData.put("Remarks", remarks);
58 | entityData.put("Properties", entityProperties(invoker));
59 | entityData.put("Methods", entityMethods(invoker));
60 | String filePath = FileUtil.getSourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPackageName())
61 | + StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getEntity());
62 | String fileName = className + ".java";
63 | // 生成Entity文件
64 | FileUtil.generateToJava(FreemarkerConfigUtil.TYPE_ENTITY, entityData, filePath, fileName);
65 | }
66 |
67 | /**
68 | * 生成实体类属性字段
69 | *
70 | * @param invoker 执行器
71 | * @return 属性代码段
72 | */
73 | public String entityProperties(AbstractInvoker invoker) {
74 | StringBuilder sb = new StringBuilder();
75 | tableInfos.forEach(ForEachUtil.withIndex((info, index) -> {
76 | if (info.getColumnName().equals(invoker.getForeignKey())) {
77 | return;
78 | }
79 | sb.append(index == 0 ? "" : Constant.SPACE_4);
80 | generateRemarks(sb, info);
81 | generateORMAnnotation(sb, info);
82 | sb.append(Constant.SPACE_4).append(String.format("private %s %s;\n", info.getPropertyType(), info.getPropertyName()));
83 | sb.append("\n");
84 | }));
85 | // 生成父表实体类时,直接截断后续生成依赖关系的代码
86 | if (Mode.ENTITY_PARENT.equals(mode)) {
87 | return sb.toString();
88 | }
89 | if (!StringUtil.isEmpty(invoker.getRelationalTableName()) || !StringUtil.isEmpty(invoker.getParentForeignKey())) {
90 | // 多对多 or 一对多
91 | sb.append(Constant.SPACE_4).append(String.format("private List<%s> %ss;\n", invoker.getParentClassName(),
92 | StringUtil.firstToLowerCase(invoker.getParentClassName())));
93 | sb.append("\n");
94 | } else if (!StringUtil.isEmpty(invoker.getForeignKey())) {
95 | // 多对一
96 | sb.append(Constant.SPACE_4).append(String.format("private %s %s;\n", invoker.getParentClassName(),
97 | StringUtil.firstToLowerCase(invoker.getParentClassName())));
98 | sb.append("\n");
99 | }
100 | return sb.toString();
101 | }
102 |
103 | /**
104 | * 生成实体类存取方法
105 | *
106 | * @param invoker 执行器
107 | * @return 方法代码段
108 | */
109 | public String entityMethods(AbstractInvoker invoker) {
110 | if (ConfigUtil.getConfiguration().isLombokEnable()) {
111 | return "";
112 | }
113 | StringBuilder sb = new StringBuilder();
114 | tableInfos.forEach(ForEachUtil.withIndex((info, index) -> {
115 | if (info.getColumnName().equals(invoker.getForeignKey())) {
116 | return;
117 | }
118 | String setter = String.format("public void set%s (%s %s) { this.%s = %s; } \n\n", StringUtil.firstToUpperCase(info.getPropertyName()),
119 | info.getPropertyType(), info.getPropertyName(), info.getPropertyName(), info.getPropertyName());
120 | sb.append(index == 0 ? "" : Constant.SPACE_4).append(setter);
121 | String getter;
122 | if (info.getPropertyType().equals("boolean")) {
123 | getter = String.format("public %s is%s () { return this.%s; } \n\n", info.getPropertyType(),
124 | StringUtil.firstToUpperCase(info.getPropertyName()), info.getPropertyName());
125 | } else {
126 | getter = String.format("public %s get%s () { return this.%s; } \n\n", info.getPropertyType(),
127 | StringUtil.firstToUpperCase(info.getPropertyName()), info.getPropertyName());
128 | }
129 | sb.append(Constant.SPACE_4).append(getter);
130 | }));
131 | // 生成父表实体类时,直接截断后续生成依赖关系的代码
132 | if (Mode.ENTITY_PARENT.equals(mode)) {
133 | return sb.toString();
134 | }
135 | if (!StringUtil.isEmpty(invoker.getRelationalTableName()) || !StringUtil.isEmpty(invoker.getParentForeignKey())) {
136 | // 多对多
137 | String setter = String.format("public void set%ss (List<%s> %ss) { this.%ss = %ss; }\n\n", invoker.getParentClassName(),
138 | invoker.getParentClassName(), StringUtil.firstToLowerCase(invoker.getParentClassName()),
139 | StringUtil.firstToLowerCase(invoker.getParentClassName()), StringUtil.firstToLowerCase(invoker.getParentClassName()));
140 | sb.append(Constant.SPACE_4).append(setter);
141 | String getter = String.format("public List<%s> get%ss () { return this.%ss; }\n\n", invoker.getParentClassName(),
142 | invoker.getParentClassName(), StringUtil.firstToLowerCase(invoker.getParentClassName()));
143 | sb.append(Constant.SPACE_4).append(getter);
144 | } else if (!StringUtil.isEmpty(invoker.getForeignKey())) {
145 | // 多对一
146 | String setter = String.format("public void set%s (%s %s) { this.%s = %s; }\n\n", invoker.getParentClassName(),
147 | invoker.getParentClassName(), StringUtil.firstToLowerCase(invoker.getParentClassName()),
148 | StringUtil.firstToLowerCase(invoker.getParentClassName()), StringUtil.firstToLowerCase(invoker.getParentClassName()));
149 | sb.append(Constant.SPACE_4).append(setter);
150 | String getter = String.format("public %s get%s () { return this.%s; }\n\n", invoker.getParentClassName(), invoker.getParentClassName(),
151 | StringUtil.firstToLowerCase(invoker.getParentClassName()));
152 | sb.append(Constant.SPACE_4).append(getter);
153 | }
154 | return sb.toString();
155 | }
156 |
157 | /**
158 | * 为实体属性生成注释
159 | *
160 | * @param sb StringBuilder对象
161 | * @param info 列属性
162 | */
163 | public void generateRemarks(StringBuilder sb, ColumnInfo info) {
164 | sb.append("/**").append("\n");
165 | sb.append(Constant.SPACE_4).append(" * ").append(info.getRemarks()).append("\n");
166 | sb.append(Constant.SPACE_4).append(" */").append("\n");
167 | }
168 |
169 | /**
170 | * 为实体属性生成swagger注解
171 | * 我们不建议在entity(do)中使用swagger注解,在dto和vo中使用swagger注解更为优雅
172 | *
173 | * @param sb StringBuilder对象
174 | * @param info 列属性
175 | */
176 | public void generateSwaggerAnnotation(StringBuilder sb, ColumnInfo info) {
177 | if (!ConfigUtil.getConfiguration().isSwaggerEnable()) {
178 | return;
179 | }
180 | sb.append(String.format("@ApiModelProperty(value = \"%s\", dataType = \"%s\")",
181 | info.getRemarks(), info.getPropertyType()));
182 | sb.append("\n");
183 | }
184 |
185 | /**
186 | * 为实体属性生成Orm框架(jpa/mybatis-plus)注解
187 | *
188 | * @param sb StringBuilder对象
189 | * @param info 列属性
190 | */
191 | public void generateORMAnnotation(StringBuilder sb, ColumnInfo info) {
192 | if (ConfigUtil.getConfiguration().isMybatisPlusEnable()) {
193 | if (info.isPrimaryKey()) {
194 | if (ConfigUtil.getConfiguration().getIdStrategy() == null || ConfigUtil.getConfiguration().getIdStrategy() == IdStrategy.AUTO) {
195 | sb.append(Constant.SPACE_4).append(String.format("@TableId(value = \"%s\", type = IdType.AUTO)\n", info.getColumnName()));
196 | } else if (ConfigUtil.getConfiguration().getIdStrategy() == IdStrategy.UUID) {
197 | sb.append(Constant.SPACE_4).append(String.format("@TableId(value = \"%s\", type = IdType.ASSIGN_UUID)\n", info.getColumnName()));
198 | }
199 | } else {
200 | sb.append(Constant.SPACE_4).append(String.format("@TableField(value = \"%s\")\n", info.getColumnName()));
201 | }
202 | } else if (ConfigUtil.getConfiguration().isJpaEnable()) {
203 | if (info.isPrimaryKey()) {
204 | if (ConfigUtil.getConfiguration().getIdStrategy() == null || ConfigUtil.getConfiguration().getIdStrategy() == IdStrategy.AUTO) {
205 | sb.append(Constant.SPACE_4).append("@Id\n");
206 | sb.append(Constant.SPACE_4).append("@GeneratedValue(strategy = GenerationType.IDENTITY)\n");
207 | } else if (ConfigUtil.getConfiguration().getIdStrategy() == IdStrategy.UUID) {
208 | sb.append(Constant.SPACE_4).append("@Id\n");
209 | sb.append(Constant.SPACE_4).append("@GeneratedValue(generator = \"uuidGenerator\")\n");
210 | sb.append(Constant.SPACE_4).append("@GenericGenerator(name = \"uuidGenerator\", strategy = \"uuid\")\n");
211 | }
212 | }
213 | sb.append(Constant.SPACE_4).append(String.format("@Column(name = \"%s\")\n", info.getColumnName()));
214 | }
215 | }
216 |
217 | }
218 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/InterfaceTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task;
2 |
3 | import com.greedystar.generator.entity.Constant;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.task.base.AbstractTask;
6 | import com.greedystar.generator.utils.*;
7 | import freemarker.template.TemplateException;
8 |
9 | import java.io.IOException;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | /**
14 | * @author GreedyStar
15 | * @since 2019/1/24
16 | */
17 | public class InterfaceTask extends AbstractTask {
18 |
19 | public InterfaceTask(AbstractInvoker invoker) {
20 | this.invoker = invoker;
21 | }
22 |
23 | @Override
24 | public void run() throws IOException, TemplateException {
25 | // 构造Service接口填充数据
26 | Map interfaceData = new HashMap<>();
27 | interfaceData.put("Configuration", ConfigUtil.getConfiguration());
28 | interfaceData.put("ClassName", ConfigUtil.getConfiguration().getName().getEntity().replace(Constant.PLACEHOLDER,
29 | invoker.getClassName()));
30 | interfaceData.put("EntityName", StringUtil.firstToLowerCase(invoker.getClassName()));
31 | interfaceData.put("InterfaceClassName", ConfigUtil.getConfiguration().getName().getInterf()
32 | .replace(Constant.PLACEHOLDER, invoker.getClassName()));
33 | String filePath = FileUtil.getSourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPackageName())
34 | + StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getInterf());
35 | String fileName = ConfigUtil.getConfiguration().getName().getInterf().replace(Constant.PLACEHOLDER, invoker.getClassName()) + ".java";
36 | // 生成Service接口文件
37 | FileUtil.generateToJava(FreemarkerConfigUtil.TYPE_INTERFACE, interfaceData, filePath, fileName);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/MapperTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task;
2 |
3 | import com.greedystar.generator.entity.ColumnInfo;
4 | import com.greedystar.generator.entity.Constant;
5 | import com.greedystar.generator.invoker.base.AbstractInvoker;
6 | import com.greedystar.generator.task.base.AbstractTask;
7 | import com.greedystar.generator.utils.*;
8 | import freemarker.template.TemplateException;
9 |
10 | import java.io.IOException;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | /**
16 | * @author GreedyStar
17 | * @since 2018/4/20
18 | */
19 | public class MapperTask extends AbstractTask {
20 |
21 | public MapperTask(AbstractInvoker invoker) {
22 | this.invoker = invoker;
23 | }
24 |
25 | @Override
26 | public void run() throws IOException, TemplateException {
27 | // 构造Mapper填充数据
28 | Map mapperData = new HashMap<>();
29 | mapperData.put("Configuration", ConfigUtil.getConfiguration());
30 | mapperData.put("ClassName", ConfigUtil.getConfiguration().getName().getEntity()
31 | .replace(Constant.PLACEHOLDER, invoker.getClassName()));
32 | mapperData.put("EntityName", StringUtil.firstToLowerCase(invoker.getClassName()));
33 | mapperData.put("DaoClassName", ConfigUtil.getConfiguration().getName().getDao()
34 | .replace(Constant.PLACEHOLDER, invoker.getClassName()));
35 | mapperData.put("TableName", invoker.getTableName());
36 | mapperData.put("PrimaryKey", getPrimaryKeyColumnInfo(invoker.getTableInfos()).getColumnName());
37 | mapperData.put("WhereId", "#{" + getPrimaryKeyColumnInfo(invoker.getTableInfos()).getPropertyName() + "}");
38 | mapperData.put("PrimaryColumn", getPrimaryKeyColumnInfo(invoker.getTableInfos()));
39 | mapperData.put("InsertProperties", insertProperties());
40 | mapperData.put("ColumnMap", columnMap());
41 | mapperData.put("ResultMap", resultMap());
42 | mapperData.put("InsertBatchValues", insertBatchValues());
43 | mapperData.put("InsertValues", insertValues());
44 | mapperData.put("UpdateProperties", updateProperties());
45 | mapperData.put("Joins", joins());
46 | if (!StringUtil.isEmpty(invoker.getRelationalTableName())) {
47 | // 多对多
48 | mapperData.put("Association", "");
49 | mapperData.put("Collection", collection());
50 | } else if (!StringUtil.isEmpty(invoker.getParentForeignKey())) {
51 | // 多对一
52 | mapperData.put("Association", "");
53 | mapperData.put("Collection", collection());
54 | } else if (!StringUtil.isEmpty(invoker.getForeignKey())) {
55 | // 一对多
56 | mapperData.put("Association", association());
57 | mapperData.put("Collection", "");
58 | } else {
59 | // 单表
60 | mapperData.put("Association", "");
61 | mapperData.put("Collection", "");
62 | }
63 | String filePath;
64 | if (ConfigUtil.getConfiguration().isMapperUnderSource()) {
65 | // mapper-under-source = true,表示将Mapper映射文件放在源文件目录下
66 | filePath = FileUtil.getSourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPackageName())
67 | + StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getMapper());
68 | } else {
69 | // 默认情况下,将Mapper映射文件放在resources下
70 | filePath = FileUtil.getResourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getMapper());
71 | }
72 | String fileName = ConfigUtil.getConfiguration().getName().getMapper().replace(Constant.PLACEHOLDER, invoker.getClassName()) + ".xml";
73 | // 生成Mapper文件
74 | FileUtil.generateToJava(FreemarkerConfigUtil.TYPE_MAPPER, mapperData, filePath, fileName);
75 | }
76 |
77 | /**
78 | * 获取主键列
79 | *
80 | * @param list
81 | * @return
82 | */
83 | private ColumnInfo getPrimaryKeyColumnInfo(List list) {
84 | for (ColumnInfo columnInfo : list) {
85 | if (columnInfo.isPrimaryKey()) {
86 | return columnInfo;
87 | }
88 | }
89 | return null;
90 | }
91 |
92 | /**
93 | * 生成columnMap
94 | *
95 | * @return ColumnMap代码段
96 | */
97 | public String columnMap() {
98 | StringBuilder sb = new StringBuilder();
99 | invoker.getTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
100 | if (info.getColumnName().equals(invoker.getForeignKey())) {
101 | return;
102 | }
103 | sb.append(index == 0 ? "" : Constant.SPACE_8);
104 | sb.append(String.format("`%s`.`%s`,\n", invoker.getTableName(), info.getColumnName()));
105 | }));
106 | if (invoker.getParentTableInfos() != null) {
107 | invoker.getParentTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
108 | sb.append(Constant.SPACE_8);
109 | if (!StringUtil.isEmpty(invoker.getRelationalTableName()) || !StringUtil.isEmpty(invoker.getParentForeignKey())) {
110 | sb.append(String.format("`%s`.`%s` AS `%ss.%s`,\n", invoker.getParentTableName(), info.getColumnName(),
111 | StringUtil.firstToLowerCase(invoker.getParentClassName()), info.getColumnName()));
112 | } else {
113 | sb.append(String.format("`%s`.`%s` AS `%s.%s`,\n", invoker.getParentTableName(), info.getColumnName(),
114 | StringUtil.firstToLowerCase(invoker.getParentClassName()), info.getColumnName()));
115 | }
116 | }));
117 | }
118 | return sb.toString().substring(0, sb.toString().length() - 2);
119 | }
120 |
121 | /**
122 | * 生成resultMap
123 | *
124 | * @return ResultMap代码段
125 | */
126 | public String resultMap() {
127 | StringBuilder sb = new StringBuilder();
128 | invoker.getTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
129 | if (info.getColumnName().equals(invoker.getForeignKey())) {
130 | return;
131 | }
132 | sb.append(index == 0 ? "" : Constant.SPACE_8);
133 | if (info.isPrimaryKey()) {
134 | sb.append(String.format("\n", info.getColumnName(), info.getPropertyName()));
135 | } else {
136 | sb.append(String.format("\n", info.getColumnName(), info.getPropertyName()));
137 | }
138 | }));
139 | return sb.toString();
140 | }
141 |
142 | /**
143 | * 生成association
144 | *
145 | * @return association代码段
146 | */
147 | public String association() {
148 | StringBuilder sb = new StringBuilder();
149 | sb.append(String.format("\n", StringUtil.firstToLowerCase(invoker.getParentClassName()),
150 | ConfigUtil.getConfiguration().getPackageName() + "." + ConfigUtil.getConfiguration().getPath().getEntity(),
151 | invoker.getParentClassName()));
152 | invoker.getParentTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
153 | if (info.isPrimaryKey()) {
154 | sb.append(Constant.SPACE_12).append(String.format("\n",
155 | StringUtil.firstToLowerCase(invoker.getParentClassName()), info.getColumnName(), info.getPropertyName()));
156 | } else {
157 | sb.append(Constant.SPACE_12).append(String.format("\n",
158 | StringUtil.firstToLowerCase(invoker.getParentClassName()), info.getColumnName(), info.getPropertyName()));
159 | }
160 | }));
161 | sb.append(Constant.SPACE_8).append("");
162 | return sb.toString();
163 | }
164 |
165 | /**
166 | * 生成collection
167 | *
168 | * @return collection代码段
169 | */
170 | public String collection() {
171 | StringBuilder sb = new StringBuilder();
172 | sb.append(String.format("\n ", StringUtil.firstToLowerCase(invoker.getParentClassName()),
173 | ConfigUtil.getConfiguration().getPackageName() + "." + ConfigUtil.getConfiguration().getPath().getEntity(),
174 | invoker.getParentClassName()));
175 | invoker.getParentTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
176 | if (info.isPrimaryKey()) {
177 | sb.append(Constant.SPACE_12).append(String.format("\n",
178 | StringUtil.firstToLowerCase(invoker.getParentClassName()), info.getColumnName(), info.getPropertyName()));
179 | } else {
180 | sb.append(Constant.SPACE_12).append(String.format("\n",
181 | StringUtil.firstToLowerCase(invoker.getParentClassName()), info.getColumnName(), info.getPropertyName()));
182 | }
183 | }));
184 | sb.append(Constant.SPACE_8).append("");
185 | return sb.toString();
186 | }
187 |
188 | /**
189 | * 生成insertProperties
190 | *
191 | * @return insertProperties代码段
192 | */
193 | public String insertProperties() {
194 | StringBuilder sb = new StringBuilder();
195 | invoker.getTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
196 | sb.append(index == 0 ? "" : Constant.SPACE_12);
197 | sb.append(String.format("`%s`,\n", info.getColumnName()));
198 | }));
199 | return sb.toString().substring(0, sb.toString().length() - 2);
200 | }
201 |
202 | /**
203 | * 生成insertValues
204 | *
205 | * @return insertValues代码段
206 | */
207 | public String insertValues() {
208 | StringBuilder sb = new StringBuilder();
209 | invoker.getTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
210 | sb.append(index == 0 ? "" : Constant.SPACE_12);
211 | if (StringUtil.isEmpty(invoker.getRelationalTableName()) && !StringUtil.isEmpty(invoker.getForeignKey())) {
212 | if (info.getColumnName().equals(invoker.getForeignKey())) {
213 | sb.append(String.format("#{%s.%s},\n", StringUtil.firstToLowerCase(invoker.getParentClassName()),
214 | getPrimaryKeyColumnInfo(invoker.getParentTableInfos()).getPropertyName()));
215 | } else {
216 | sb.append(String.format("#{%s},\n", info.getPropertyName()));
217 | }
218 | } else {
219 | sb.append(String.format("#{%s},\n", info.getPropertyName()));
220 | }
221 | }));
222 | return sb.toString().substring(0, sb.toString().length() - 2);
223 | }
224 |
225 | /**
226 | * 生成insertBatchValues
227 | *
228 | * @return insertBatchValues代码段
229 | */
230 | public String insertBatchValues() {
231 | StringBuilder sb = new StringBuilder();
232 | invoker.getTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
233 | sb.append(index == 0 ? "" : Constant.SPACE_12);
234 | if (StringUtil.isEmpty(invoker.getRelationalTableName()) && !StringUtil.isEmpty(invoker.getForeignKey())) {
235 | if (info.getColumnName().equals(invoker.getForeignKey())) {
236 | sb.append(String.format("#{%s.%s.%s},\n", StringUtil.firstToLowerCase(invoker.getClassName()),
237 | StringUtil.firstToLowerCase(invoker.getParentClassName()),
238 | getPrimaryKeyColumnInfo(invoker.getParentTableInfos()).getPropertyName()));
239 | } else {
240 | sb.append(String.format("#{%s.%s},\n", StringUtil.firstToLowerCase(invoker.getClassName()), info.getPropertyName()));
241 | }
242 | } else {
243 | sb.append(String.format("#{%s.%s},\n", StringUtil.firstToLowerCase(invoker.getClassName()), info.getPropertyName()));
244 | }
245 | }));
246 | return sb.toString().substring(0, sb.toString().length() - 2);
247 | }
248 |
249 | /**
250 | * 生成updateProperties
251 | *
252 | * @return updateProperties代码段
253 | */
254 | public String updateProperties() {
255 | StringBuilder sb = new StringBuilder();
256 | invoker.getTableInfos().forEach(ForEachUtil.withIndex((info, index) -> {
257 | sb.append(index == 0 ? "" : Constant.SPACE_8);
258 | if (StringUtil.isEmpty(invoker.getRelationalTableName()) && !StringUtil.isEmpty(invoker.getForeignKey())) {
259 | if (info.getColumnName().equals(invoker.getForeignKey())) {
260 | sb.append(String.format("`%s` = #{%s.%s},\n", info.getColumnName(),
261 | StringUtil.firstToLowerCase(invoker.getParentClassName()),
262 | getPrimaryKeyColumnInfo(invoker.getParentTableInfos()).getPropertyName()));
263 | } else {
264 | sb.append(String.format("`%s` = #{%s},\n", info.getColumnName(), info.getPropertyName()));
265 | }
266 | } else {
267 | sb.append(String.format("`%s` = #{%s},\n", info.getColumnName(), info.getPropertyName()));
268 | }
269 | }));
270 | return sb.toString().substring(0, sb.toString().length() - 2);
271 | }
272 |
273 | /**
274 | * 生成joins代码段
275 | *
276 | * @return joins代码段
277 | */
278 | public String joins() {
279 | StringBuilder sb = new StringBuilder();
280 | if (!StringUtil.isEmpty(invoker.getRelationalTableName())) {
281 | // 多对多
282 | sb.append(String.format("LEFT JOIN `%s` ON `%s`.`%s` = `%s`.`%s`", invoker.getRelationalTableName(),
283 | invoker.getRelationalTableName(), invoker.getForeignKey(), invoker.getTableName(),
284 | getPrimaryKeyColumnInfo(invoker.getTableInfos()).getColumnName()));
285 | sb.append("\n").append(Constant.SPACE_8);
286 | sb.append(String.format("LEFT JOIN `%s` ON `%s`.`%s` = `%s`.`%s`", invoker.getParentTableName(),
287 | invoker.getParentTableName(), getPrimaryKeyColumnInfo(invoker.getParentTableInfos()).getColumnName(),
288 | invoker.getRelationalTableName(), invoker.getParentForeignKey()));
289 | } else if (!StringUtil.isEmpty(invoker.getParentForeignKey())) {
290 | // 一对多
291 | sb.append(String.format("LEFT JOIN `%s` ON `%s`.`%s` = `%s`.`%s`", invoker.getParentTableName(),
292 | invoker.getParentTableName(), invoker.getParentForeignKey(), invoker.getTableName(),
293 | getPrimaryKeyColumnInfo(invoker.getTableInfos()).getColumnName()));
294 | } else if (!StringUtil.isEmpty(invoker.getForeignKey())) {
295 | // 多对一
296 | sb.append(String.format("LEFT JOIN `%s` ON `%s`.%s = `%s`.`%s`", invoker.getParentTableName(),
297 | invoker.getParentTableName(), getPrimaryKeyColumnInfo(invoker.getParentTableInfos()).getColumnName(),
298 | invoker.getTableName(), invoker.getForeignKey()));
299 | }
300 | return sb.toString();
301 | }
302 |
303 | }
304 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/ServiceTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task;
2 |
3 | import com.greedystar.generator.entity.Constant;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.task.base.AbstractTask;
6 | import com.greedystar.generator.utils.*;
7 | import freemarker.template.TemplateException;
8 |
9 | import java.io.IOException;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 |
13 | /**
14 | * @author GreedyStar
15 | * @since 2018/4/20
16 | */
17 | public class ServiceTask extends AbstractTask {
18 |
19 | public ServiceTask(AbstractInvoker invoker) {
20 | this.invoker = invoker;
21 | }
22 |
23 | @Override
24 | public void run() throws IOException, TemplateException {
25 | // 构造Service填充数据
26 | Map serviceData = new HashMap<>();
27 | serviceData.put("Configuration", ConfigUtil.getConfiguration());
28 | serviceData.put("ClassName", ConfigUtil.getConfiguration().getName().getEntity().replace(Constant.PLACEHOLDER, invoker.getClassName()));
29 | serviceData.put("EntityName", StringUtil.firstToLowerCase(invoker.getClassName()));
30 | serviceData.put("DaoClassName", ConfigUtil.getConfiguration().getName().getDao().replace(Constant.PLACEHOLDER, invoker.getClassName()));
31 | serviceData.put("DaoEntityName", StringUtil.firstToLowerCase(ConfigUtil.getConfiguration().getName().getDao()
32 | .replace(Constant.PLACEHOLDER, invoker.getClassName())));
33 | String filePath = FileUtil.getSourcePath() + StringUtil.package2Path(ConfigUtil.getConfiguration().getPackageName())
34 | + StringUtil.package2Path(ConfigUtil.getConfiguration().getPath().getService());
35 | String fileName;
36 | /*
37 | * 根据用户是否配置了path节点下的interf属性来判断是否采用接口+实现类的方式
38 | */
39 | String serviceClassName = ConfigUtil.getConfiguration().getName().getService().replace(Constant.PLACEHOLDER, invoker.getClassName());
40 | if (StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getInterf())) {
41 | serviceData.put("ServiceClassName", serviceClassName);
42 | serviceData.put("Implements", "");
43 | serviceData.put("InterfaceImport", "");
44 | serviceData.put("Override", "");
45 | fileName = ConfigUtil.getConfiguration().getName().getService().replace(Constant.PLACEHOLDER, invoker.getClassName()) + ".java";
46 | } else {
47 | // Service接口实现类默认由Impl结尾
48 | serviceClassName = serviceClassName.contains("Impl") ? serviceClassName : serviceClassName + "Impl";
49 | serviceData.put("ServiceClassName", serviceClassName);
50 | serviceData.put("Implements", "implements " + ConfigUtil.getConfiguration().getName().getInterf()
51 | .replace(Constant.PLACEHOLDER, invoker.getClassName()));
52 | serviceData.put("InterfaceImport", "import " + ConfigUtil.getConfiguration().getPackageName() + "."
53 | + ConfigUtil.getConfiguration().getPath().getInterf() + "."
54 | + ConfigUtil.getConfiguration().getName().getInterf().replace(Constant.PLACEHOLDER, invoker.getClassName()) + ";");
55 | serviceData.put("Override", "\n @Override");
56 | fileName = serviceClassName + ".java";
57 | }
58 | // 生成Service文件
59 | FileUtil.generateToJava(FreemarkerConfigUtil.TYPE_SERVICE, serviceData, filePath, fileName);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/task/base/AbstractTask.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.task.base;
2 |
3 | import com.greedystar.generator.invoker.base.AbstractInvoker;
4 | import freemarker.template.TemplateException;
5 |
6 | import java.io.IOException;
7 | import java.io.Serializable;
8 |
9 | /**
10 | * @author GreedyStar
11 | * @since 2018/4/20
12 | */
13 | public abstract class AbstractTask implements Serializable {
14 | protected AbstractInvoker invoker;
15 |
16 | public AbstractTask() {
17 | }
18 |
19 | /**
20 | * 执行任务
21 | *
22 | * @throws IOException 文件读写异常
23 | * @throws TemplateException 模板异常
24 | */
25 | public abstract void run() throws IOException, TemplateException;
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/ConfigUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import com.greedystar.generator.entity.Configuration;
4 | import com.greedystar.generator.entity.Constant;
5 | import org.yaml.snakeyaml.Yaml;
6 |
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.net.URL;
10 |
11 | /**
12 | * 代码生成器的配置工具
13 | *
14 | * @author GreedyStar
15 | * @since 2018/9/7
16 | */
17 | public class ConfigUtil {
18 | /**
19 | * 代码生成器的配置信息
20 | */
21 | private static volatile Configuration configuration;
22 |
23 | /**
24 | * 获取配置信息
25 | *
26 | * @return 配置对象
27 | */
28 | public static Configuration getConfiguration() {
29 | // ConfigUtil.getConfiguration()会在生成代码之前调用(获取业务表元数据),这里为null通常表示用户通过generator.yaml进行配置,
30 | if (null == ConfigUtil.configuration) {
31 | synchronized (ConfigUtil.class) {
32 | if (null == ConfigUtil.configuration) {
33 | readConfigurationFromFile(); // 从配置文件中读取配置信息
34 | }
35 | }
36 | }
37 | return ConfigUtil.configuration;
38 | }
39 |
40 | /**
41 | * 设置配置信息,提供给用户的外部配置接口,使用该接口则不会再到generator.yaml下读取配置
42 | *
43 | * @param configuration 配置对象
44 | */
45 | public static void setConfiguration(Configuration configuration) {
46 | ConfigUtil.configuration = configuration;
47 | checkConfiguration();
48 | }
49 |
50 | /**
51 | * 通过generator.yaml读取配置
52 | */
53 | private static void readConfigurationFromFile() {
54 | try {
55 | URL url = ConfigUtil.class.getClassLoader().getResource("generator.yaml");
56 | if (null == url || url.getPath().contains("jar")) {
57 | System.err.println("Can not find file named 'generator.yaml' under resources path, please make sure that you have defined that file.");
58 | System.exit(0);
59 | } else {
60 | String configStr = StringUtil.line2Camel(IOUtils.toString((InputStream) url.getContent()));
61 | InputStream inputStream = IOUtils.toInputStream(configStr);
62 | Yaml yaml = new Yaml();
63 | ConfigUtil.setConfiguration(yaml.loadAs(inputStream, Configuration.class));
64 | }
65 | } catch (IOException e) {
66 | e.printStackTrace();
67 | System.exit(0);
68 | }
69 | }
70 |
71 | /**
72 | * 检查配置信息,用户可通过geneartor.yaml进行配置,或通过代码手动进行配置
73 | */
74 | private static void checkConfiguration() {
75 | try {
76 | // 用户未配置类名后缀,那么添加一个默认的空对象,这里是为了保证在用户不配置name属性时,程序能够取得默认值
77 | if (null == ConfigUtil.configuration.getName()) {
78 | Configuration.Name nameConfig = new Configuration.Name();
79 | if (ConfigUtil.configuration.isJpaEnable()) {
80 | nameConfig.setDao(Constant.PLACEHOLDER + "Repository");
81 | } else if (ConfigUtil.configuration.isMybatisPlusEnable()) {
82 | nameConfig.setDao(Constant.PLACEHOLDER + "Mapper");
83 | }
84 | ConfigUtil.configuration.setName(nameConfig);
85 | }
86 | // 检查db属性
87 | if (null == ConfigUtil.configuration.getDb()) {
88 | throw new Exception("Can not find configuration attribute named 'db', please make sure that you have configured that attribute.");
89 | }
90 | // 检查path属性
91 | if (null == ConfigUtil.configuration.getPath()) {
92 | throw new Exception("Can not find configuration attribute named 'path', please make sure that you have configured that attribute.");
93 | }
94 | // 检查db属性是否配置
95 | if (StringUtil.isEmpty(ConfigUtil.configuration.getDb().getUrl()) || StringUtil.isEmpty(ConfigUtil.configuration.getDb().getUsername())) {
96 | throw new Exception("Please configure the correct db connection parameters, i.e. url, username and password.");
97 | }
98 | // 检查顶级包名是否配置
99 | if (StringUtil.isEmpty(ConfigUtil.configuration.getPackageName())) {
100 | throw new Exception("Please configure the correct attribute named 'package-name' or 'packageName'.");
101 | }
102 | // 检查是否同时启用了jpa和mybatis-plus模式
103 | if (ConfigUtil.configuration.isMybatisPlusEnable() && ConfigUtil.configuration.isJpaEnable()) {
104 | throw new Exception("Can not enable JPA mode and MyBatis-Plus mode at the same time.");
105 | } else if (ConfigUtil.configuration.isMybatisPlusEnable() || ConfigUtil.configuration.isJpaEnable()) {
106 | // 禁止生成mapper.xml
107 | ConfigUtil.configuration.getPath().setMapper(null);
108 | }
109 | } catch (Exception e) {
110 | e.printStackTrace();
111 | System.exit(0);
112 | }
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/ConvertorUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import com.greedystar.generator.convertor.DefaultConvertor;
4 | import com.greedystar.generator.convertor.TypeConvertor;
5 |
6 | import java.sql.JDBCType;
7 |
8 | /**
9 | * 类型转换器工具类
10 | *
11 | * @author GreedyStar
12 | * @since 2018/4/19
13 | */
14 | public class ConvertorUtil {
15 | /**
16 | * 类型转换器
17 | */
18 | private volatile static TypeConvertor convertor;
19 |
20 | /**
21 | * 将数据库数据类型转换为Java数据类型
22 | *
23 | * @param type jdbc类型
24 | * @return java类型
25 | */
26 | public static String parseTypeFormSqlType(JDBCType type) {
27 | /*
28 | * 用户配置了错误的TypeConvertor会导致convertor为null
29 | * 在生成多表关系代码时,会有两个EntityTask并发执行,防止创建多个实例,采用double-check的单例模式
30 | */
31 | if (convertor == null) {
32 | synchronized (ConvertorUtil.class) {
33 | if (convertor == null) {
34 | convertor = newInstance();
35 | }
36 | }
37 | }
38 | return convertor.convertType(type);
39 | }
40 |
41 | private static TypeConvertor newInstance() {
42 | TypeConvertor convertor;
43 | String convertorClass = ConfigUtil.getConfiguration().getConvertor();
44 | if (StringUtil.isEmpty(convertorClass)) { // 用户未配置类型转换器,使用默认转换器
45 | convertor = new DefaultConvertor();
46 | } else {
47 | // 加载用户定义的类型转换器
48 | try {
49 | Class clazz = Class.forName(ConfigUtil.getConfiguration().getConvertor());
50 | convertor = (TypeConvertor) clazz.newInstance();
51 | } catch (Exception e) {
52 | System.err.println(String.format("Can not find %s, DefaultConvertor will be used.", convertorClass));
53 | convertor = new DefaultConvertor();
54 | }
55 | }
56 | return convertor;
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/FileUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import freemarker.template.Template;
4 | import freemarker.template.TemplateException;
5 |
6 | import java.io.*;
7 |
8 | /**
9 | * @author GreedyStar
10 | * @since 2018/4/19
11 | */
12 | public class FileUtil {
13 |
14 | /**
15 | * @param type 使用模板类型
16 | * @param data 填充数据
17 | * @param filePath 输出文件
18 | * @param fileName 文件名
19 | * @throws IOException 文件读写异常
20 | * @throws TemplateException 模板异常
21 | */
22 | public static void generateToJava(int type, Object data, String filePath, String fileName) throws IOException, TemplateException {
23 | String path = filePath + fileName; // 待生成的代码文件路径
24 | // 已存在的文件不予覆盖
25 | File file = new File(path);
26 | if (file.exists() && !ConfigUtil.getConfiguration().isFileOverride()) {
27 | path += ".generated";
28 | System.err.printf("%s already exit. Generating %s \n", fileName, path);
29 | } else {
30 | System.out.printf("Generating %s \n", path);
31 | }
32 | // 代码生成路径目录不存在则自动创建
33 | if (!file.getParentFile().exists()) {
34 | file.getParentFile().mkdirs();
35 | }
36 | Template tpl = getTemplate(type); // 获取模板文件
37 | // 填充数据
38 | StringWriter writer = new StringWriter();
39 | tpl.process(data, writer);
40 | writer.flush();
41 | // 写入文件
42 | FileOutputStream fos = new FileOutputStream(path);
43 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
44 | BufferedWriter bw = new BufferedWriter(osw, 1024);
45 | tpl.process(data, bw);
46 | writer.close();
47 | bw.close();
48 | }
49 |
50 | /**
51 | * 获取模板
52 | *
53 | * @param type 模板类型
54 | * @return
55 | * @throws IOException
56 | */
57 | private static Template getTemplate(int type) throws IOException {
58 | switch (type) {
59 | case FreemarkerConfigUtil.TYPE_ENTITY:
60 | return FreemarkerConfigUtil.getInstance().getTemplate("Entity.ftl");
61 | case FreemarkerConfigUtil.TYPE_DAO:
62 | return FreemarkerConfigUtil.getInstance().getTemplate("Dao.ftl");
63 | case FreemarkerConfigUtil.TYPE_SERVICE:
64 | return FreemarkerConfigUtil.getInstance().getTemplate("Service.ftl");
65 | case FreemarkerConfigUtil.TYPE_CONTROLLER:
66 | return FreemarkerConfigUtil.getInstance().getTemplate("Controller.ftl");
67 | case FreemarkerConfigUtil.TYPE_MAPPER:
68 | return FreemarkerConfigUtil.getInstance().getTemplate("Mapper.ftl");
69 | case FreemarkerConfigUtil.TYPE_INTERFACE:
70 | return FreemarkerConfigUtil.getInstance().getTemplate("Interface.ftl");
71 | default:
72 | return null;
73 | }
74 | }
75 |
76 | /**
77 | * 获取项目主目录
78 | *
79 | * @return 项目根路径
80 | */
81 | private static String getBasicProjectPath() {
82 | StringBuilder sb = new StringBuilder();
83 | String path = FileUtil.class.getClassLoader().getResource("").getPath().replace("/", File.separator);
84 | if (path.contains("target")) {
85 | sb.append(path, 0, path.indexOf("target"));
86 | } else if (path.contains("build")) {
87 | sb.append(path, 0, path.indexOf("build"));
88 | }
89 | sb.append("src").append(File.separator).append("main").append(File.separator);
90 | return sb.toString();
91 | }
92 |
93 | /**
94 | * 获取源码路径
95 | *
96 | * @return 源码路径
97 | */
98 | public static String getSourcePath() {
99 | StringBuilder sb = new StringBuilder();
100 | sb.append(getBasicProjectPath()).append("java").append(File.separator);
101 | return sb.toString();
102 | }
103 |
104 | /**
105 | * 获取资源文件路径
106 | *
107 | * @return 资源路径
108 | */
109 | public static String getResourcePath() {
110 | StringBuilder sb = new StringBuilder();
111 | sb.append(getBasicProjectPath()).append("resources").append(File.separator);
112 | return sb.toString();
113 | }
114 |
115 | public static void main(String[] args) {
116 | System.out.println(getResourcePath());
117 | System.out.println(getSourcePath());
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/ForEachUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import java.util.function.BiConsumer;
4 | import java.util.function.Consumer;
5 |
6 | /**
7 | * @author GreedyStar
8 | * @since 2020/8/1
9 | */
10 | public class ForEachUtil {
11 |
12 | /**
13 | * 带索引的foreach工具
14 | *
15 | * @param consumer consumer
16 | * @param 泛型
17 | * @return consumer
18 | */
19 | public static Consumer withIndex(BiConsumer consumer) {
20 | Index index = new Index();
21 | return t -> {
22 | int i = index.value++;
23 | consumer.accept(t, i);
24 | };
25 | }
26 |
27 | private static class Index {
28 | int value;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/FreemarkerConfigUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import freemarker.template.Configuration;
4 |
5 | import java.io.File;
6 | import java.io.IOException;
7 | import java.util.Locale;
8 |
9 | /**
10 | * @author GreedyStar
11 | * @since 2018/4/19
12 | */
13 | public class FreemarkerConfigUtil {
14 | /**
15 | * 模板路径
16 | */
17 | private static String path = new File(FreemarkerConfigUtil.class.getClassLoader().getResource("ftls").getFile()).getPath();
18 | /**
19 | * freemarker配置
20 | */
21 | private static volatile Configuration configuration;
22 | public final static int TYPE_ENTITY = 0;
23 | public final static int TYPE_DAO = 1;
24 | public final static int TYPE_SERVICE = 2;
25 | public final static int TYPE_CONTROLLER = 3;
26 | public final static int TYPE_MAPPER = 4;
27 | public final static int TYPE_INTERFACE = 5;
28 |
29 | public static Configuration getInstance() {
30 | if (null == configuration) {
31 | synchronized (FreemarkerConfigUtil.class) {
32 | if (null == configuration) {
33 | configuration = new Configuration(Configuration.VERSION_2_3_23);
34 | try {
35 | if (path.contains("jar")) {
36 | configuration.setClassForTemplateLoading(FreemarkerConfigUtil.class, "/ftls");
37 | } else {
38 | configuration.setDirectoryForTemplateLoading(new File(path));
39 | }
40 | } catch (IOException e) {
41 | e.printStackTrace();
42 | }
43 | configuration.setEncoding(Locale.CHINA, "utf-8");
44 | }
45 | }
46 | }
47 | return configuration;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/IOUtils.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import java.io.*;
4 | import java.nio.charset.StandardCharsets;
5 | import java.sql.SQLException;
6 |
7 | /**
8 | * @author GreedyStar
9 | * @since 2021-4-27
10 | */
11 | public class IOUtils {
12 |
13 | /**
14 | * 输入流转字符串
15 | *
16 | * @param inputStream 输入流
17 | * @return 转换后的字符串
18 | * @throws IOException IOException
19 | */
20 | public static String toString(InputStream inputStream) throws IOException {
21 | StringBuilder sb = new StringBuilder();
22 | String line;
23 | BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
24 | while ((line = br.readLine()) != null) {
25 | sb.append(line);
26 | }
27 | return sb.toString();
28 | }
29 |
30 | /**
31 | * 字符串转输入流
32 | *
33 | * @param string 字符串
34 | * @return 转换后的输入流
35 | */
36 | public static InputStream toInputStream(String string) {
37 | return new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8));
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/StringUtil.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * @author GreedyStar
7 | * @since 2018-09-10
8 | */
9 | public class StringUtil {
10 |
11 | /**
12 | * 判断字符串是否为空
13 | *
14 | * @param string 待检测字符串
15 | * @return 是否为空
16 | */
17 | public static boolean isEmpty(String string) {
18 | if (string == null || string.trim().equals("")) {
19 | return true;
20 | } else {
21 | return false;
22 | }
23 | }
24 |
25 | /**
26 | * 首字母大写
27 | *
28 | * @param string 待处理字符串
29 | * @return 处理后字符串
30 | */
31 | public static String firstToUpperCase(String string) {
32 | StringBuilder sb = new StringBuilder();
33 | sb.append(string.substring(0, 1).toUpperCase()).append(string.substring(1));
34 | return sb.toString();
35 | }
36 |
37 |
38 | /**
39 | * 首字母小写
40 | *
41 | * @param string 待处理字符串
42 | * @return 处理后字符串
43 | */
44 | public static String firstToLowerCase(String string) {
45 | StringBuilder sb = new StringBuilder();
46 | sb.append(string.substring(0, 1).toLowerCase()).append(string.substring(1));
47 | return sb.toString();
48 | }
49 |
50 | /**
51 | * 数据库列名转换为实体的属性名
52 | *
53 | * @param columnName 列名
54 | * @return 转换后的实体属性名
55 | */
56 | public static String columnName2PropertyName(String columnName) {
57 | if (isEmpty(columnName)) {
58 | return "";
59 | }
60 | if (!columnName.contains("_")) { // 列名中不包含 “_”
61 | if (isAllUpperCase(columnName)) {
62 | return columnName.toLowerCase();
63 | }
64 | return columnName;
65 | }
66 | StringBuilder sb = new StringBuilder();
67 | String[] str = columnName.toLowerCase().split("_");
68 | sb.append(str[0]);
69 | for (int i = 1; i < str.length; i++) {
70 | sb.append(firstToUpperCase(str[i]));
71 | }
72 | return sb.toString();
73 | }
74 |
75 | /**
76 | * 以驼峰命名法生成类名,用于未指定类名时自动生成类名,如sys_user自动生成类名SysUser
77 | *
78 | * @param tableName 表名
79 | * @return 驼峰命名类名
80 | */
81 | public static String tableName2ClassName(String tableName) {
82 | String[] nameStrs = tableName.split("_");
83 | StringBuilder sb = new StringBuilder();
84 | for (String string : nameStrs) {
85 | sb.append(string.substring(0, 1).toUpperCase()).append(string.substring(1));
86 | }
87 | return sb.toString();
88 | }
89 |
90 | /**
91 | * 给定字符串除特定符号外的字符是否全部大写
92 | *
93 | * @param string 待检测字符串
94 | * @return 是否全大写
95 | */
96 | public static boolean isAllUpperCase(String string) {
97 | for (Character c : string.replace("_", "").toCharArray()) {
98 | if (!Character.isUpperCase(c)) {
99 | return false;
100 | }
101 | }
102 | return true;
103 | }
104 |
105 | /**
106 | * 包名转换为文件系统路径
107 | *
108 | * @param packageName 包名
109 | * @return 文件系统路径
110 | */
111 | public static String package2Path(String packageName) {
112 | if (StringUtil.isEmpty(packageName)) {
113 | return "";
114 | }
115 | StringBuilder sb = new StringBuilder();
116 | String[] packages = packageName.split("\\.");
117 | for (String str : packages) {
118 | sb.append(str).append(File.separator);
119 | }
120 | return sb.toString();
121 | }
122 |
123 | /**
124 | * 短横线转驼峰
125 | *
126 | * @param str 待转换字符串
127 | * @return 驼峰命名字符串
128 | */
129 | public static String line2Camel(String str) {
130 | return str.replace("package-name", "packageName")
131 | .replace("lombok-enable", "lombokEnable")
132 | .replace("mapper-under-source", "mapperUnderSource")
133 | .replace("swagger-enable", "swaggerEnable")
134 | .replace("mybatis-plus-enable", "mybatisPlusEnable")
135 | .replace("jpa-enable", "jpaEnable")
136 | .replace("id-strategy", "idStrategy")
137 | .replace("file-override", "fileOverride");
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/src/main/java/com/greedystar/generator/utils/TaskQueue.java:
--------------------------------------------------------------------------------
1 | package com.greedystar.generator.utils;
2 |
3 | import com.greedystar.generator.entity.Mode;
4 | import com.greedystar.generator.invoker.base.AbstractInvoker;
5 | import com.greedystar.generator.task.*;
6 | import com.greedystar.generator.task.base.AbstractTask;
7 |
8 | import java.util.LinkedList;
9 |
10 | /**
11 | * @author GreedyStar
12 | * @since 2018-11-27
13 | */
14 | public class TaskQueue {
15 |
16 | /**
17 | * 任务队列
18 | */
19 | private LinkedList taskQueue = new LinkedList<>();
20 |
21 | /**
22 | * 初始化共性任务,包括Controller、ServiceImpl、Service、Dao、Mapper任务
23 | *
24 | * @param invoker 执行器
25 | */
26 | private void initCommonTasks(AbstractInvoker invoker) {
27 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getController())) {
28 | taskQueue.add(new ControllerTask(invoker));
29 | }
30 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getService())) {
31 | taskQueue.add(new ServiceTask(invoker));
32 | }
33 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getInterf())) {
34 | taskQueue.add(new InterfaceTask(invoker));
35 | }
36 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getDao())) {
37 | taskQueue.add(new DaoTask(invoker));
38 | }
39 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getMapper())) {
40 | taskQueue.add(new MapperTask(invoker));
41 | }
42 | }
43 |
44 | /**
45 | * 初始化单表生成任务,包括Entity、Mapper任务
46 | *
47 | * @param invoker 执行器
48 | */
49 | public void initSingleTasks(AbstractInvoker invoker) {
50 | initCommonTasks(invoker);
51 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getEntity())) {
52 | taskQueue.add(new EntityTask(Mode.ENTITY_MAIN, invoker));
53 | }
54 | }
55 |
56 | /**
57 | * 初始化单表生成任务,包括Entity、Mapper任务
58 | *
59 | * @param invoker 执行器
60 | */
61 | public void initMany2OneTasks(AbstractInvoker invoker) {
62 | initCommonTasks(invoker);
63 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getEntity())) {
64 | taskQueue.add(new EntityTask(Mode.ENTITY_MAIN, invoker));
65 | taskQueue.add(new EntityTask(Mode.ENTITY_PARENT, invoker));
66 | }
67 | }
68 |
69 | /**
70 | * 初始化单表生成任务,包括Entity、Mapper任务
71 | *
72 | * @param invoker 执行器
73 | */
74 | public void initOne2ManyTasks(AbstractInvoker invoker) {
75 | initCommonTasks(invoker);
76 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getEntity())) {
77 | taskQueue.add(new EntityTask(Mode.ENTITY_MAIN, invoker));
78 | taskQueue.add(new EntityTask(Mode.ENTITY_PARENT, invoker));
79 | }
80 | }
81 |
82 | /**
83 | * 初始化单表生成任务,包括Entity、Mapper任务
84 | *
85 | * @param invoker 执行器
86 | */
87 | public void initMany2ManyTasks(AbstractInvoker invoker) {
88 | initCommonTasks(invoker);
89 | if (!StringUtil.isEmpty(ConfigUtil.getConfiguration().getPath().getEntity())) {
90 | taskQueue.add(new EntityTask(Mode.ENTITY_MAIN, invoker));
91 | taskQueue.add(new EntityTask(Mode.ENTITY_PARENT, invoker));
92 | }
93 | }
94 |
95 | /**
96 | * 任务队列是否为空
97 | *
98 | * @return 是否为空
99 | */
100 | public boolean isEmpty() {
101 | return taskQueue.isEmpty();
102 | }
103 |
104 | /**
105 | * 取出一个任务
106 | *
107 | * @return 任务
108 | */
109 | public AbstractTask poll() {
110 | return taskQueue.poll();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/resources/ftls/Controller.ftl:
--------------------------------------------------------------------------------
1 | package ${Configuration.packageName}.${Configuration.path.controller};
2 |
3 | import ${Configuration.packageName}.${Configuration.path.entity}.${ClassName};
4 | ${ServiceImport}
5 | <#if Configuration.swaggerEnable>
6 | import io.swagger.annotations.Api;
7 | import io.swagger.annotations.ApiOperation;
8 | #if>
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import java.io.Serializable;
13 | import java.util.HashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | /**
18 | * @author ${Configuration.author}
19 | * @date ${.now?date}
20 | */
21 | <#if Configuration.swaggerEnable>
22 | @Api(value = "/${EntityName}", tags = "${EntityName}管理接口")
23 | #if>
24 | @RestController
25 | @RequestMapping(value = "/${EntityName}")
26 | public class ${ControllerClassName} {
27 | @Autowired
28 | private ${ServiceClassName} ${ServiceEntityName};
29 |
30 | <#if Configuration.swaggerEnable>
31 | @ApiOperation(value = "查询${EntityName}列表", httpMethod = "GET")
32 | #if>
33 | @GetMapping(value = "")
34 | public Object list() {
35 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
36 | List<${ClassName}> ${EntityName}s = ${ServiceEntityName}.list();
37 | <#else><#-- mybatis或jpa模式 -->
38 | List<${ClassName}> ${EntityName}s = ${ServiceEntityName}.findAll();
39 | #if>
40 | Map result = new HashMap<>();
41 | result.put("data", ${EntityName}s);
42 | result.put("status", 200);
43 | result.put("message", "OK");
44 | return result;
45 | }
46 |
47 | <#if Configuration.swaggerEnable>
48 | @ApiOperation(value = "查看${EntityName}详情", httpMethod = "GET")
49 | #if>
50 | @GetMapping(value = "/{id}")
51 | public Object get(@PathVariable("id") ${pkType} id) {
52 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
53 | ${ClassName} ${EntityName} = ${ServiceEntityName}.getById(id);
54 | <#else><#-- mybatis或jpa模式 -->
55 | ${ClassName} ${EntityName} = ${ServiceEntityName}.get(id);
56 | #if>
57 | Map result = new HashMap<>();
58 | result.put("data", ${EntityName});
59 | result.put("status", 200);
60 | result.put("message", "OK");
61 | return result;
62 | }
63 |
64 | <#if Configuration.swaggerEnable>
65 | @ApiOperation(value = "创建${EntityName}", httpMethod = "POST")
66 | #if>
67 | @PostMapping(value = "")
68 | public Object post(@RequestBody ${ClassName} ${EntityName}) {
69 | Map result = new HashMap<>();
70 | try {
71 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
72 | ${ServiceEntityName}.save(${EntityName});
73 | <#else><#-- mybatis或jpa模式 -->
74 | ${ServiceEntityName}.insert(${EntityName});
75 | #if>
76 | result.put("status", 200);
77 | result.put("message", "OK");
78 | } catch (Exception e) {
79 | e.printStackTrace();
80 | result.put("status", 500);
81 | result.put("message", "ERROR");
82 | }
83 | return result;
84 | }
85 |
86 | <#if Configuration.swaggerEnable>
87 | @ApiOperation(value = "修改${EntityName}信息", httpMethod = "PUT")
88 | #if>
89 | @PutMapping(value = "")
90 | public Object put(@RequestBody ${ClassName} ${EntityName}) {
91 | Map result = new HashMap<>();
92 | try {
93 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
94 | ${ServiceEntityName}.updateById(${EntityName});
95 | <#else><#-- mybatis或jpa模式 -->
96 | ${ServiceEntityName}.update(${EntityName});
97 | #if>
98 | result.put("status", 200);
99 | result.put("message", "OK");
100 | } catch (Exception e) {
101 | e.printStackTrace();
102 | result.put("status", 500);
103 | result.put("message", "ERROR");
104 | }
105 | return result;
106 | }
107 |
108 |
109 | <#if Configuration.swaggerEnable>
110 | @ApiOperation(value = "删除${EntityName}", httpMethod = "DELETE")
111 | #if>
112 | @DeleteMapping(value = "")
113 | public Object delete(@RequestBody ${ClassName} ${EntityName}) {
114 | Map result = new HashMap<>();
115 | try {
116 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
117 | ${ServiceEntityName}.removeById(${EntityName}.getId());
118 | <#else><#-- mybatis或jpa模式 -->
119 | ${ServiceEntityName}.delete(${EntityName});
120 | #if>
121 | result.put("status", 200);
122 | result.put("message", "OK");
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | result.put("status", 500);
126 | result.put("message", "ERROR");
127 | }
128 | return result;
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/resources/ftls/Dao.ftl:
--------------------------------------------------------------------------------
1 | package ${Configuration.packageName}.${Configuration.path.dao};
2 |
3 | import ${Configuration.packageName}.${Configuration.path.entity}.${ClassName};
4 | <#if Configuration.mybatisPlusEnable>
5 | import org.apache.ibatis.annotations.Mapper;
6 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
7 | <#elseif Configuration.jpaEnable>
8 | import org.springframework.data.jpa.repository.JpaRepository;
9 | import org.springframework.stereotype.Repository;
10 | <#else>
11 | import org.apache.ibatis.annotations.Mapper;
12 | #if>
13 |
14 | import java.io.Serializable;
15 | import java.util.List;
16 |
17 | /**
18 | * @author ${Configuration.author}
19 | * @date ${.now?date}
20 | */
21 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
22 | @Mapper
23 | public interface ${DaoClassName} extends BaseMapper<${ClassName}> {
24 |
25 | }
26 | <#elseif Configuration.jpaEnable><#-- jpa模式 -->
27 | @Repository
28 | public interface ${DaoClassName} extends JpaRepository<${ClassName}, Serializable> {
29 |
30 | }
31 | <#else><#-- mybatis模式 -->
32 | @Mapper
33 | public interface ${DaoClassName} {
34 |
35 | ${ClassName} get(Serializable id);
36 |
37 | List<${ClassName}> findAll();
38 |
39 | int insert(${ClassName} ${EntityName});
40 |
41 | int insertBatch(List<${ClassName}> ${EntityName}s);
42 |
43 | int update(${ClassName} ${EntityName});
44 |
45 | int delete(${ClassName} ${EntityName});
46 |
47 | }
48 | #if>
--------------------------------------------------------------------------------
/src/main/resources/ftls/Entity.ftl:
--------------------------------------------------------------------------------
1 | package ${Configuration.packageName}.${Configuration.path.entity};
2 |
3 | <#if Configuration.lombokEnable>
4 | import lombok.Data;
5 | #if>
6 | <#if Configuration.mybatisPlusEnable>
7 | import com.baomidou.mybatisplus.annotation.*;
8 | <#elseif Configuration.jpaEnable>
9 | import javax.persistence.*;
10 | import org.hibernate.annotations.GenericGenerator;
11 | #if>
12 | import java.io.Serializable;
13 | import java.math.BigDecimal;
14 | import java.util.Date;
15 | import java.util.List;
16 |
17 | /**
18 | * ${Remarks}
19 | *
20 | * @author ${Configuration.author}
21 | * @date ${.now?date}
22 | */
23 | <#if Configuration.lombokEnable>
24 | @Data
25 | #if>
26 | <#if Configuration.mybatisPlusEnable>
27 | @TableName(value = "${TableName}")
28 | <#elseif Configuration.jpaEnable>
29 | @Entity
30 | @Table(name = "${TableName}")
31 | #if>
32 | public class ${ClassName} implements Serializable {
33 | ${Properties}
34 |
35 | ${Methods}
36 | }
--------------------------------------------------------------------------------
/src/main/resources/ftls/Interface.ftl:
--------------------------------------------------------------------------------
1 | package ${Configuration.packageName}.${Configuration.path.interf};
2 |
3 | import ${Configuration.packageName}.${Configuration.path.entity}.${ClassName};
4 | <#if Configuration.mybatisPlusEnable>
5 | import com.baomidou.mybatisplus.extension.service.IService;
6 | <#else>
7 | import java.io.Serializable;
8 | #if>
9 | import java.io.Serializable;
10 | import java.util.List;
11 |
12 | /**
13 | * @author ${Configuration.author}
14 | * @date ${.now?date}
15 | */
16 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
17 | public interface ${InterfaceClassName} extends IService<${ClassName}> {
18 |
19 | }
20 | <#else><#-- mybatis或jpa模式 -->
21 | public interface ${InterfaceClassName} {
22 |
23 | <#if Configuration.jpaEnable><#-- jpa模式 -->
24 | ${ClassName} get(Serializable id);
25 |
26 | List<${ClassName}> findAll();
27 |
28 | ${ClassName} insert(${ClassName} ${EntityName});
29 |
30 | List<${ClassName}> insertBatch(List<${ClassName}> ${EntityName}s);
31 |
32 | ${ClassName} update(${ClassName} ${EntityName});
33 |
34 | void delete(${ClassName} ${EntityName});
35 |
36 | <#else><#-- mybatis模式 -->
37 | ${ClassName} get(Serializable id);
38 |
39 | List<${ClassName}> findAll();
40 |
41 | int insert(${ClassName} ${EntityName});
42 |
43 | int insertBatch(List<${ClassName}> ${EntityName}s);
44 |
45 | int update(${ClassName} ${EntityName});
46 |
47 | int delete(${ClassName} ${EntityName});
48 |
49 | #if>
50 | }
51 | #if>
52 |
--------------------------------------------------------------------------------
/src/main/resources/ftls/Mapper.ftl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ${ResultMap}
7 | ${Association}
8 | ${Collection}
9 |
10 |
11 |
12 | ${ColumnMap}
13 |
14 |
15 |
16 | ${Joins}
17 |
18 |
19 |
27 |
28 |
35 |
36 |
37 | INSERT INTO `${TableName}`(
38 | ${InsertProperties}
39 | )
40 | VALUES (
41 | ${InsertValues}
42 | )
43 |
44 |
45 |
46 | INSERT INTO ${TableName}(
47 | ${InsertProperties}
48 | )
49 | VALUES
50 |
51 | (
52 | ${InsertBatchValues}
53 | )
54 |
55 |
56 |
57 |
58 | UPDATE `${TableName}` SET
59 | ${UpdateProperties}
60 | WHERE `${PrimaryColumn.columnName}` = ${r"#{"}${PrimaryColumn.propertyName}${r"}"}
61 |
62 |
63 |
64 | DELETE FROM `${TableName}`
65 | WHERE `${PrimaryColumn.columnName}` = ${r"#{"}${PrimaryColumn.propertyName}${r"}"}
66 |
67 |
68 |
--------------------------------------------------------------------------------
/src/main/resources/ftls/Service.ftl:
--------------------------------------------------------------------------------
1 | package ${Configuration.packageName}.${Configuration.path.service};
2 |
3 | import ${Configuration.packageName}.${Configuration.path.dao}.${DaoClassName};
4 | import ${Configuration.packageName}.${Configuration.path.entity}.${ClassName};
5 | ${InterfaceImport}
6 | <#if Configuration.mybatisPlusEnable>
7 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
8 | <#else>
9 | import java.io.Serializable;
10 | #if>
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Service;
13 |
14 | import java.io.Serializable;
15 | import java.util.List;
16 |
17 | /**
18 | * @author ${Configuration.author}
19 | * @date ${.now?date}
20 | */
21 | @Service
22 | <#if Configuration.mybatisPlusEnable><#-- mybatis-plus模式 -->
23 | public class ${ServiceClassName} extends ServiceImpl<${DaoClassName}, ${ClassName}> ${Implements} {
24 |
25 | }
26 | <#else><#-- mybatis或jpa模式 -->
27 | public class ${ServiceClassName} ${Implements} {
28 | @Autowired
29 | private ${DaoClassName} ${DaoEntityName};
30 | <#if Configuration.jpaEnable><#-- jpa模式 -->
31 | ${Override}
32 | public ${ClassName} get(Serializable id) {
33 | return ${DaoEntityName}.findById(id).orElse(null);
34 | }
35 | ${Override}
36 | public List<${ClassName}> findAll() {
37 | return ${DaoEntityName}.findAll();
38 | }
39 | ${Override}
40 | public ${ClassName} insert(${ClassName} ${EntityName}) {
41 | return ${DaoEntityName}.save(${EntityName});
42 | }
43 | ${Override}
44 | public List<${ClassName}> insertBatch(List<${ClassName}> ${EntityName}s){
45 | return ${DaoEntityName}.saveAll(${EntityName}s);
46 | }
47 | ${Override}
48 | public ${ClassName} update(${ClassName} ${EntityName}) {
49 | return ${DaoEntityName}.save(${EntityName});
50 | }
51 | ${Override}
52 | public void delete(${ClassName} ${EntityName}) {
53 | ${DaoEntityName}.delete(${EntityName});
54 | }
55 | <#else><#-- mybatis模式 -->
56 | ${Override}
57 | public ${ClassName} get(Serializable id) {
58 | return ${DaoEntityName}.get(id);
59 | }
60 | ${Override}
61 | public List<${ClassName}> findAll() {
62 | return ${DaoEntityName}.findAll();
63 | }
64 | ${Override}
65 | public int insert(${ClassName} ${EntityName}) {
66 | return ${DaoEntityName}.insert(${EntityName});
67 | }
68 | ${Override}
69 | public int insertBatch(List<${ClassName}> ${EntityName}s) {
70 | return ${DaoEntityName}.insertBatch(${EntityName}s);
71 | }
72 | ${Override}
73 | public int update(${ClassName} ${EntityName}) {
74 | return ${DaoEntityName}.update(${EntityName});
75 | }
76 | ${Override}
77 | public int delete(${ClassName} ${EntityName}) {
78 | return ${DaoEntityName}.delete(${EntityName});
79 | }
80 | #if>
81 | }
82 | #if>
--------------------------------------------------------------------------------