1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.generator.plugins;
17
18 import static org.mybatis.generator.internal.util.StringUtility.isTrue;
19
20 import static org.mybatis.generator.internal.util.JavaBeansUtil.getGetterMethodName;
21
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Properties;
25
26 import org.mybatis.generator.api.PluginAdapter;
27 import org.mybatis.generator.api.IntrospectedColumn;
28 import org.mybatis.generator.api.IntrospectedTable;
29 import org.mybatis.generator.api.dom.OutputUtilities;
30 import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
31 import org.mybatis.generator.api.dom.java.JavaVisibility;
32 import org.mybatis.generator.api.dom.java.Method;
33 import org.mybatis.generator.api.dom.java.Parameter;
34 import org.mybatis.generator.api.dom.java.TopLevelClass;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class EqualsHashCodePlugin extends PluginAdapter {
52
53 private boolean useEqualsHashCodeFromRoot;
54
55 @Override
56 public void setProperties(Properties properties) {
57 super.setProperties(properties);
58 useEqualsHashCodeFromRoot = isTrue(properties.getProperty("useEqualsHashCodeFromRoot"));
59 }
60
61
62
63
64 public boolean validate(List<String> warnings) {
65 return true;
66 }
67
68 @Override
69 public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass,
70 IntrospectedTable introspectedTable) {
71 List<IntrospectedColumn> columns;
72 if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
73 columns = introspectedTable.getNonBLOBColumns();
74 } else {
75 columns = introspectedTable.getAllColumns();
76 }
77
78 generateEquals(topLevelClass, columns, introspectedTable);
79 generateHashCode(topLevelClass, columns, introspectedTable);
80
81 return true;
82 }
83
84 @Override
85 public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass,
86 IntrospectedTable introspectedTable) {
87 generateEquals(topLevelClass, introspectedTable.getPrimaryKeyColumns(),
88 introspectedTable);
89 generateHashCode(topLevelClass, introspectedTable
90 .getPrimaryKeyColumns(), introspectedTable);
91
92 return true;
93 }
94
95 @Override
96 public boolean modelRecordWithBLOBsClassGenerated(
97 TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
98 generateEquals(topLevelClass, introspectedTable.getAllColumns(),
99 introspectedTable);
100 generateHashCode(topLevelClass, introspectedTable.getAllColumns(),
101 introspectedTable);
102
103 return true;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 protected void generateEquals(TopLevelClass topLevelClass,
124 List<IntrospectedColumn> introspectedColumns,
125 IntrospectedTable introspectedTable) {
126 Method method = new Method();
127 method.setVisibility(JavaVisibility.PUBLIC);
128 method.setReturnType(FullyQualifiedJavaType
129 .getBooleanPrimitiveInstance());
130 method.setName("equals");
131 method.addParameter(new Parameter(FullyQualifiedJavaType
132 .getObjectInstance(), "that"));
133 if (introspectedTable.isJava5Targeted()) {
134 method.addAnnotation("@Override");
135 }
136
137 context.getCommentGenerator().addGeneralMethodComment(method,
138 introspectedTable);
139
140 method.addBodyLine("if (this == that) {");
141 method.addBodyLine("return true;");
142 method.addBodyLine("}");
143
144 method.addBodyLine("if (that == null) {");
145 method.addBodyLine("return false;");
146 method.addBodyLine("}");
147
148 method.addBodyLine("if (getClass() != that.getClass()) {");
149 method.addBodyLine("return false;");
150 method.addBodyLine("}");
151
152 StringBuilder sb = new StringBuilder();
153 sb.append(topLevelClass.getType().getShortName());
154 sb.append(" other = (");
155 sb.append(topLevelClass.getType().getShortName());
156 sb.append(") that;");
157 method.addBodyLine(sb.toString());
158
159 if (useEqualsHashCodeFromRoot && topLevelClass.getSuperClass() != null) {
160 method.addBodyLine("if (!super.equals(other)) {");
161 method.addBodyLine("return false;");
162 method.addBodyLine("}");
163 }
164
165 boolean first = true;
166 Iterator<IntrospectedColumn> iter = introspectedColumns.iterator();
167 while (iter.hasNext()) {
168 IntrospectedColumn introspectedColumn = iter.next();
169
170 sb.setLength(0);
171
172 if (first) {
173 sb.append("return (");
174 first = false;
175 } else {
176 OutputUtilities.javaIndent(sb, 1);
177 sb.append("&& (");
178 }
179
180 String getterMethod = getGetterMethodName(
181 introspectedColumn.getJavaProperty(), introspectedColumn
182 .getFullyQualifiedJavaType());
183
184 if (introspectedColumn.getFullyQualifiedJavaType().isPrimitive()) {
185 sb.append("this.");
186 sb.append(getterMethod);
187 sb.append("() == ");
188 sb.append("other.");
189 sb.append(getterMethod);
190 sb.append("())");
191 } else if (introspectedColumn.getFullyQualifiedJavaType().isArray()) {
192 topLevelClass.addImportedType("java.util.Arrays");
193 sb.append("Arrays.equals(this.");
194 sb.append(getterMethod);
195 sb.append("(), ");
196 sb.append("other.");
197 sb.append(getterMethod);
198 sb.append("()))");
199 } else {
200 sb.append("this.");
201 sb.append(getterMethod);
202 sb.append("() == null ? other.");
203 sb.append(getterMethod);
204 sb.append("() == null : this.");
205 sb.append(getterMethod);
206 sb.append("().equals(other.");
207 sb.append(getterMethod);
208 sb.append("()))");
209 }
210
211 if (!iter.hasNext()) {
212 sb.append(';');
213 }
214
215 method.addBodyLine(sb.toString());
216 }
217
218 topLevelClass.addMethod(method);
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 protected void generateHashCode(TopLevelClass topLevelClass,
236 List<IntrospectedColumn> introspectedColumns,
237 IntrospectedTable introspectedTable) {
238 Method method = new Method();
239 method.setVisibility(JavaVisibility.PUBLIC);
240 method.setReturnType(FullyQualifiedJavaType.getIntInstance());
241 method.setName("hashCode");
242 if (introspectedTable.isJava5Targeted()) {
243 method.addAnnotation("@Override");
244 }
245
246 context.getCommentGenerator().addGeneralMethodComment(method,
247 introspectedTable);
248
249 method.addBodyLine("final int prime = 31;");
250 method.addBodyLine("int result = 1;");
251
252 if (useEqualsHashCodeFromRoot && topLevelClass.getSuperClass() != null) {
253 method.addBodyLine("result = prime * result + super.hashCode();");
254 }
255
256 StringBuilder sb = new StringBuilder();
257 boolean hasTemp = false;
258 Iterator<IntrospectedColumn> iter = introspectedColumns.iterator();
259 while (iter.hasNext()) {
260 IntrospectedColumn introspectedColumn = iter.next();
261
262 FullyQualifiedJavaType fqjt = introspectedColumn
263 .getFullyQualifiedJavaType();
264
265 String getterMethod = getGetterMethodName(
266 introspectedColumn.getJavaProperty(), fqjt);
267
268 sb.setLength(0);
269 if (fqjt.isPrimitive()) {
270 if ("boolean".equals(fqjt.getFullyQualifiedName())) {
271 sb.append("result = prime * result + (");
272 sb.append(getterMethod);
273 sb.append("() ? 1231 : 1237);");
274 method.addBodyLine(sb.toString());
275 } else if ("byte".equals(fqjt.getFullyQualifiedName())) {
276 sb.append("result = prime * result + ");
277 sb.append(getterMethod);
278 sb.append("();");
279 method.addBodyLine(sb.toString());
280 } else if ("char".equals(fqjt.getFullyQualifiedName())) {
281 sb.append("result = prime * result + ");
282 sb.append(getterMethod);
283 sb.append("();");
284 method.addBodyLine(sb.toString());
285 } else if ("double".equals(fqjt.getFullyQualifiedName())) {
286 if (!hasTemp) {
287 method.addBodyLine("long temp;");
288 hasTemp = true;
289 }
290 sb.append("temp = Double.doubleToLongBits(");
291 sb.append(getterMethod);
292 sb.append("());");
293 method.addBodyLine(sb.toString());
294 method
295 .addBodyLine("result = prime * result + (int) (temp ^ (temp >>> 32));");
296 } else if ("float".equals(fqjt.getFullyQualifiedName())) {
297 sb
298 .append("result = prime * result + Float.floatToIntBits(");
299 sb.append(getterMethod);
300 sb.append("());");
301 method.addBodyLine(sb.toString());
302 } else if ("int".equals(fqjt.getFullyQualifiedName())) {
303 sb.append("result = prime * result + ");
304 sb.append(getterMethod);
305 sb.append("();");
306 method.addBodyLine(sb.toString());
307 } else if ("long".equals(fqjt.getFullyQualifiedName())) {
308 sb.append("result = prime * result + (int) (");
309 sb.append(getterMethod);
310 sb.append("() ^ (");
311 sb.append(getterMethod);
312 sb.append("() >>> 32));");
313 method.addBodyLine(sb.toString());
314 } else if ("short".equals(fqjt.getFullyQualifiedName())) {
315 sb.append("result = prime * result + ");
316 sb.append(getterMethod);
317 sb.append("();");
318 method.addBodyLine(sb.toString());
319 } else {
320
321 continue;
322 }
323 } else if (fqjt.isArray()) {
324
325
326 sb.append("result = prime * result + (Arrays.hashCode(");
327 sb.append(getterMethod);
328 sb.append("()));");
329 method.addBodyLine(sb.toString());
330 } else {
331 sb.append("result = prime * result + ((");
332 sb.append(getterMethod);
333 sb.append("() == null) ? 0 : ");
334 sb.append(getterMethod);
335 sb.append("().hashCode());");
336 method.addBodyLine(sb.toString());
337 }
338 }
339
340 method.addBodyLine("return result;");
341
342 topLevelClass.addMethod(method);
343 }
344 }