1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.generator.codegen.mybatis3.javamapper.elements;
17
18 import static org.mybatis.generator.api.dom.OutputUtilities.javaIndent;
19 import static org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities.getEscapedColumnName;
20 import static org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities.getParameterClause;
21 import static org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities.getRenamedColumnNameForResultMap;
22 import static org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities.getSelectListPhrase;
23 import static org.mybatis.generator.internal.util.StringUtility.escapeStringForJava;
24 import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
25
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Optional;
32 import java.util.Set;
33
34 import org.mybatis.generator.api.IntrospectedColumn;
35 import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
36 import org.mybatis.generator.api.dom.java.Interface;
37 import org.mybatis.generator.api.dom.java.JavaVisibility;
38 import org.mybatis.generator.api.dom.java.Method;
39 import org.mybatis.generator.api.dom.java.Parameter;
40 import org.mybatis.generator.codegen.AbstractGenerator;
41 import org.mybatis.generator.codegen.mybatis3.ListUtilities;
42 import org.mybatis.generator.config.GeneratedKey;
43
44 public abstract class AbstractJavaMapperMethodGenerator extends AbstractGenerator {
45 public abstract void addInterfaceElements(Interface interfaze);
46
47 protected AbstractJavaMapperMethodGenerator() {
48 super();
49 }
50
51 protected static String getResultAnnotation(Interface interfaze, IntrospectedColumn introspectedColumn,
52 boolean idColumn, boolean constructorBased) {
53 StringBuilder sb = new StringBuilder();
54 if (constructorBased) {
55 interfaze.addImportedType(introspectedColumn.getFullyQualifiedJavaType());
56 sb.append("@Arg(column=\"");
57 sb.append(getRenamedColumnNameForResultMap(introspectedColumn));
58 sb.append("\", javaType=");
59 sb.append(introspectedColumn.getFullyQualifiedJavaType().getShortName());
60 sb.append(".class");
61 } else {
62 sb.append("@Result(column=\"");
63 sb.append(getRenamedColumnNameForResultMap(introspectedColumn));
64 sb.append("\", property=\"");
65 sb.append(introspectedColumn.getJavaProperty());
66 sb.append('\"');
67 }
68
69 if (stringHasValue(introspectedColumn.getTypeHandler())) {
70 FullyQualifiedJavaType fqjt = new FullyQualifiedJavaType(introspectedColumn.getTypeHandler());
71 interfaze.addImportedType(fqjt);
72 sb.append(", typeHandler=");
73 sb.append(fqjt.getShortName());
74 sb.append(".class");
75 }
76
77 sb.append(", jdbcType=JdbcType.");
78 sb.append(introspectedColumn.getJdbcTypeName());
79 if (idColumn) {
80 sb.append(", id=true");
81 }
82 sb.append(')');
83
84 return sb.toString();
85 }
86
87 protected Optional<String> buildGeneratedKeyAnnotation() {
88 return introspectedTable.getGeneratedKey().flatMap(this::buildGeneratedKeyAnnotation);
89 }
90
91 private Optional<String> buildGeneratedKeyAnnotation(GeneratedKey gk) {
92 return introspectedTable.getColumn(gk.getColumn()).map(ic -> buildGeneratedKeyAnnotation(gk, ic));
93 }
94
95 private String buildGeneratedKeyAnnotation(GeneratedKey gk, IntrospectedColumn introspectedColumn) {
96 StringBuilder sb = new StringBuilder();
97 if (gk.isJdbcStandard()) {
98 sb.append("@Options(useGeneratedKeys=true,keyProperty=\"");
99 sb.append(introspectedColumn.getJavaProperty());
100 sb.append("\")");
101 } else {
102 sb.append("@SelectKey(statement=\"");
103 sb.append(gk.getRuntimeSqlStatement());
104 sb.append("\", keyProperty=\"");
105 sb.append(introspectedColumn.getJavaProperty());
106 sb.append("\", before=");
107 sb.append(gk.isIdentity() ? "false" : "true");
108 sb.append(", resultType=");
109 sb.append(introspectedColumn.getFullyQualifiedJavaType().getShortName());
110 sb.append(".class)");
111 }
112 return sb.toString();
113 }
114
115 protected Set<FullyQualifiedJavaType> buildGeneratedKeyImportsIfRequired() {
116 return introspectedTable.getGeneratedKey().map(this::buildGeneratedKeyImportsIfRequired)
117 .orElseGet(Collections::emptySet);
118 }
119
120 private Set<FullyQualifiedJavaType> buildGeneratedKeyImportsIfRequired(GeneratedKey gk) {
121 return introspectedTable.getColumn(gk.getColumn()).map(ic -> buildGeneratedKeyImports(gk, ic))
122 .orElseGet(Collections::emptySet);
123 }
124
125 private Set<FullyQualifiedJavaType> buildGeneratedKeyImports(GeneratedKey gk,
126 IntrospectedColumn introspectedColumn) {
127 Set<FullyQualifiedJavaType> answer = new HashSet<>();
128 if (gk.isJdbcStandard()) {
129 answer.add(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Options"));
130 } else {
131 answer.add(new FullyQualifiedJavaType("org.apache.ibatis.annotations.SelectKey"));
132 answer.add(introspectedColumn.getFullyQualifiedJavaType());
133 }
134
135 return answer;
136 }
137
138 protected void addAnnotatedSelectImports(Interface interfaze) {
139 interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.type.JdbcType"));
140
141 if (introspectedTable.isConstructorBased()) {
142 interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Arg"));
143 interfaze.addImportedType(
144 new FullyQualifiedJavaType("org.apache.ibatis.annotations.ConstructorArgs"));
145 } else {
146 interfaze.addImportedType(
147 new FullyQualifiedJavaType("org.apache.ibatis.annotations.Result"));
148 interfaze.addImportedType(
149 new FullyQualifiedJavaType("org.apache.ibatis.annotations.Results"));
150 }
151 }
152
153 protected List<String> buildByPrimaryKeyWhereClause() {
154 List<String> answer = new ArrayList<>();
155 StringBuilder sb = new StringBuilder();
156 boolean and = false;
157 Iterator<IntrospectedColumn> iter = introspectedTable.getPrimaryKeyColumns().iterator();
158 while (iter.hasNext()) {
159 sb.setLength(0);
160 javaIndent(sb, 1);
161 if (and) {
162 sb.append(" \"and ");
163 } else {
164 sb.append("\"where ");
165 and = true;
166 }
167
168 IntrospectedColumn introspectedColumn = iter.next();
169 sb.append(escapeStringForJava(getEscapedColumnName(introspectedColumn)));
170 sb.append(" = ");
171 sb.append(getParameterClause(introspectedColumn));
172 sb.append('\"');
173 if (iter.hasNext()) {
174 sb.append(',');
175 }
176 answer.add(sb.toString());
177 }
178
179 return answer;
180 }
181
182 protected List<String> buildUpdateByPrimaryKeyAnnotations(List<IntrospectedColumn> columnList) {
183 List<String> answer = new ArrayList<>();
184 answer.add("@Update({");
185
186 StringBuilder sb = new StringBuilder();
187 javaIndent(sb, 1);
188 sb.append("\"update ");
189 sb.append(escapeStringForJava(introspectedTable.getFullyQualifiedTableNameAtRuntime()));
190 sb.append("\",");
191 answer.add(sb.toString());
192
193
194 sb.setLength(0);
195 javaIndent(sb, 1);
196 sb.append("\"set ");
197
198 Iterator<IntrospectedColumn> iter = ListUtilities.removeGeneratedAlwaysColumns(columnList).iterator();
199 while (iter.hasNext()) {
200 IntrospectedColumn introspectedColumn = iter.next();
201
202 sb.append(escapeStringForJava(getEscapedColumnName(introspectedColumn)));
203 sb.append(" = ");
204 sb.append(getParameterClause(introspectedColumn));
205
206 if (iter.hasNext()) {
207 sb.append(',');
208 }
209
210 sb.append("\",");
211 answer.add(sb.toString());
212
213
214 if (iter.hasNext()) {
215 sb.setLength(0);
216 javaIndent(sb, 1);
217 sb.append(" \"");
218 }
219 }
220
221 answer.addAll(buildByPrimaryKeyWhereClause());
222
223 answer.add("})");
224 return answer;
225 }
226
227 protected void addPrimaryKeyMethodParameters(boolean isSimple, Method method,
228 Set<FullyQualifiedJavaType> importedTypes) {
229 if (!isSimple && introspectedTable.getRules().generatePrimaryKeyClass()) {
230 FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getPrimaryKeyType());
231 importedTypes.add(type);
232 method.addParameter(new Parameter(type, "key"));
233 } else {
234
235
236
237 List<IntrospectedColumn> introspectedColumns = introspectedTable.getPrimaryKeyColumns();
238 boolean annotate = introspectedColumns.size() > 1;
239 if (annotate) {
240 importedTypes.add(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
241 }
242 StringBuilder sb = new StringBuilder();
243 for (IntrospectedColumn introspectedColumn : introspectedColumns) {
244 FullyQualifiedJavaType type = introspectedColumn.getFullyQualifiedJavaType();
245 importedTypes.add(type);
246 Parameter parameter = new Parameter(type, introspectedColumn.getJavaProperty());
247 if (annotate) {
248 sb.setLength(0);
249 sb.append("@Param(\"");
250 sb.append(introspectedColumn.getJavaProperty());
251 sb.append("\")");
252 parameter.addAnnotation(sb.toString());
253 }
254 method.addParameter(parameter);
255 }
256 }
257 }
258
259 protected void addAnnotatedResults(Interface interfaze, Method method,
260 List<IntrospectedColumn> nonPrimaryKeyColumns) {
261
262 if (introspectedTable.isConstructorBased()) {
263 method.addAnnotation("@ConstructorArgs({");
264 } else {
265 method.addAnnotation("@Results({");
266 }
267
268 StringBuilder sb = new StringBuilder();
269
270 Iterator<IntrospectedColumn> iterPk = introspectedTable.getPrimaryKeyColumns().iterator();
271 Iterator<IntrospectedColumn> iterNonPk = nonPrimaryKeyColumns.iterator();
272 while (iterPk.hasNext()) {
273 IntrospectedColumn introspectedColumn = iterPk.next();
274 sb.setLength(0);
275 javaIndent(sb, 1);
276 sb.append(getResultAnnotation(interfaze, introspectedColumn, true,
277 introspectedTable.isConstructorBased()));
278
279 if (iterPk.hasNext() || iterNonPk.hasNext()) {
280 sb.append(',');
281 }
282
283 method.addAnnotation(sb.toString());
284 }
285
286 while (iterNonPk.hasNext()) {
287 IntrospectedColumn introspectedColumn = iterNonPk.next();
288 sb.setLength(0);
289 javaIndent(sb, 1);
290 sb.append(getResultAnnotation(interfaze, introspectedColumn, false,
291 introspectedTable.isConstructorBased()));
292
293 if (iterNonPk.hasNext()) {
294 sb.append(',');
295 }
296
297 method.addAnnotation(sb.toString());
298 }
299
300 method.addAnnotation("})");
301 }
302
303 protected Method buildBasicUpdateByExampleMethod(String statementId, FullyQualifiedJavaType parameterType,
304 Set<FullyQualifiedJavaType> importedTypes) {
305 Method method = new Method(statementId);
306 method.setVisibility(JavaVisibility.PUBLIC);
307 method.setAbstract(true);
308 method.setReturnType(FullyQualifiedJavaType.getIntInstance());
309
310 method.addParameter(new Parameter(parameterType, "row", "@Param(\"row\")"));
311
312 importedTypes.add(parameterType);
313
314 FullyQualifiedJavaType exampleType = new FullyQualifiedJavaType(introspectedTable.getExampleType());
315 method.addParameter(new Parameter(exampleType, "example", "@Param(\"example\")"));
316 importedTypes.add(exampleType);
317
318 importedTypes.add(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Param"));
319
320 context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);
321
322 return method;
323 }
324
325 protected Method buildBasicUpdateByPrimaryKeyMethod(String statementId, FullyQualifiedJavaType parameterType) {
326 Method method = new Method(statementId);
327 method.setVisibility(JavaVisibility.PUBLIC);
328 method.setAbstract(true);
329 method.setReturnType(FullyQualifiedJavaType.getIntInstance());
330 method.addParameter(new Parameter(parameterType, "row"));
331
332 context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);
333 return method;
334 }
335
336 protected List<String> buildInitialSelectAnnotationStrings() {
337 List<String> answer = new ArrayList<>();
338 answer.add("@Select({");
339 StringBuilder sb = new StringBuilder();
340 javaIndent(sb, 1);
341 sb.append("\"select\",");
342 answer.add(sb.toString());
343
344 sb.setLength(0);
345 javaIndent(sb, 1);
346 sb.append('"');
347 boolean hasColumns = false;
348 Iterator<IntrospectedColumn> iter = introspectedTable.getAllColumns().iterator();
349 while (iter.hasNext()) {
350 sb.append(escapeStringForJava(getSelectListPhrase(iter.next())));
351 hasColumns = true;
352
353 if (iter.hasNext()) {
354 sb.append(", ");
355 }
356
357 if (sb.length() > 80) {
358 sb.append("\",");
359 answer.add(sb.toString());
360
361 sb.setLength(0);
362 javaIndent(sb, 1);
363 sb.append('"');
364 hasColumns = false;
365 }
366 }
367
368 if (hasColumns) {
369 sb.append("\",");
370 answer.add(sb.toString());
371 }
372
373 return answer;
374 }
375 }