• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / generator / 2202

05 May 2026 07:27PM UTC coverage: 91.746% (+0.04%) from 91.703%
2202

push

github

web-flow
Merge pull request #1508 from mybatis/renovate/com.github.javaparser-javaparser-core-3.x

Update dependency com.github.javaparser:javaparser-core to v3.28.1

2454 of 3154 branches covered (77.81%)

12038 of 13121 relevant lines covered (91.75%)

0.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.55
/core/mybatis-generator-core/src/main/java/org/mybatis/generator/plugins/EqualsHashCodePlugin.java
1
/*
2
 *    Copyright 2006-2026 the original author or authors.
3
 *
4
 *    Licensed under the Apache License, Version 2.0 (the "License");
5
 *    you may not use this file except in compliance with the License.
6
 *    You may obtain a copy of the License at
7
 *
8
 *       https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *    Unless required by applicable law or agreed to in writing, software
11
 *    distributed under the License is distributed on an "AS IS" BASIS,
12
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *    See the License for the specific language governing permissions and
14
 *    limitations under the License.
15
 */
16
package org.mybatis.generator.plugins;
17

18
import static org.mybatis.generator.internal.util.JavaBeansUtil.getGetterMethodName;
19
import static org.mybatis.generator.internal.util.StringUtility.isTrue;
20

21
import java.util.Iterator;
22
import java.util.List;
23
import java.util.Properties;
24

25
import org.mybatis.generator.api.IntrospectedColumn;
26
import org.mybatis.generator.api.IntrospectedTable;
27
import org.mybatis.generator.api.PluginAdapter;
28
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
29
import org.mybatis.generator.api.dom.java.JavaVisibility;
30
import org.mybatis.generator.api.dom.java.Method;
31
import org.mybatis.generator.api.dom.java.Parameter;
32
import org.mybatis.generator.api.dom.java.TopLevelClass;
33

34
/**
35
 * This plugin adds equals() and hashCode() methods to the generated model
36
 * classes. It demonstrates the process of adding methods to generated classes
37
 *
38
 * <p>The <code>equals</code> method generated by this class is correct in most cases,
39
 * but will probably NOT be correct if you have specified a rootClass - because
40
 * our equals method only checks the fields it knows about.
41
 *
42
 * <p>Similarly, the <code>hashCode</code> method generated by this class only relies
43
 * on fields it knows about. Anything you add, or fields in a super class will
44
 * not be factored into the hash code.
45
 *
46
 * @author Jeff Butler
47
 *
48
 */
49
public class EqualsHashCodePlugin extends PluginAdapter {
1✔
50

51
    private boolean useEqualsHashCodeFromRoot;
52

53
    @Override
54
    public void setProperties(Properties properties) {
55
        super.setProperties(properties);
1✔
56
        useEqualsHashCodeFromRoot = isTrue(properties.getProperty("useEqualsHashCodeFromRoot")); //$NON-NLS-1$
1✔
57
    }
1✔
58

59
    /**
60
     * This plugin is always valid - no properties are required.
61
     */
62
    @Override
63
    public boolean validate(List<String> warnings) {
64
        return true;
1✔
65
    }
66

67
    @Override
68
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass,
69
            IntrospectedTable introspectedTable) {
70
        List<IntrospectedColumn> columns;
71
        if (introspectedTable.getRules().generateRecordWithBLOBsClass()) {
1✔
72
            columns = introspectedTable.getNonBLOBColumns();
1✔
73
        } else {
74
            columns = introspectedTable.getAllColumns();
1✔
75
        }
76

77
        generateEquals(topLevelClass, columns, introspectedTable);
1✔
78
        generateHashCode(topLevelClass, columns, introspectedTable);
1✔
79

80
        return true;
1✔
81
    }
82

83
    @Override
84
    public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass,
85
            IntrospectedTable introspectedTable) {
86
        generateEquals(topLevelClass, introspectedTable.getPrimaryKeyColumns(),
1✔
87
                introspectedTable);
88
        generateHashCode(topLevelClass, introspectedTable
1✔
89
                .getPrimaryKeyColumns(), introspectedTable);
1✔
90

91
        return true;
1✔
92
    }
93

94
    @Override
95
    public boolean modelRecordWithBLOBsClassGenerated(
96
            TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
97
        generateEquals(topLevelClass, introspectedTable.getAllColumns(),
1✔
98
                introspectedTable);
99
        generateHashCode(topLevelClass, introspectedTable.getAllColumns(),
1✔
100
                introspectedTable);
101

102
        return true;
1✔
103
    }
104

105
    /**
106
     * Generates an <code>equals</code> method that does a comparison of all fields.
107
     *
108
     * <p>The generated <code>equals</code> method will be correct unless:
109
     *
110
     * <ul>
111
     *   <li>Other fields have been added to the generated classes</li>
112
     *   <li>A <code>rootClass</code> is specified that holds state</li>
113
     * </ul>
114
     *
115
     * @param topLevelClass
116
     *            the class to which the method will be added
117
     * @param introspectedColumns
118
     *            column definitions of this class and any superclass of this
119
     *            class
120
     * @param introspectedTable
121
     *            the table corresponding to this class
122
     */
123
    protected void generateEquals(TopLevelClass topLevelClass,
124
            List<IntrospectedColumn> introspectedColumns,
125
            IntrospectedTable introspectedTable) {
126
        Method method = new Method("equals"); //$NON-NLS-1$
1✔
127
        method.setVisibility(JavaVisibility.PUBLIC);
1✔
128
        method.setReturnType(FullyQualifiedJavaType
1✔
129
                .getBooleanPrimitiveInstance());
1✔
130
        method.addParameter(new Parameter(FullyQualifiedJavaType
1✔
131
                .getObjectInstance(), "that")); //$NON-NLS-1$
1✔
132
        method.addAnnotation("@Override"); //$NON-NLS-1$
1✔
133

134
        getCommentGenerator().addGeneralMethodAnnotation(method, introspectedTable, topLevelClass.getImportedTypes());
1✔
135

136
        method.addBodyLine("if (this == that) {"); //$NON-NLS-1$
1✔
137
        method.addBodyLine("return true;"); //$NON-NLS-1$
1✔
138
        method.addBodyLine("}"); //$NON-NLS-1$
1✔
139

140
        method.addBodyLine("if (that == null) {"); //$NON-NLS-1$
1✔
141
        method.addBodyLine("return false;"); //$NON-NLS-1$
1✔
142
        method.addBodyLine("}"); //$NON-NLS-1$
1✔
143

144
        method.addBodyLine("if (getClass() != that.getClass()) {"); //$NON-NLS-1$
1✔
145
        method.addBodyLine("return false;"); //$NON-NLS-1$
1✔
146
        method.addBodyLine("}"); //$NON-NLS-1$
1✔
147

148
        StringBuilder sb = new StringBuilder();
1✔
149
        sb.append(topLevelClass.getType().getShortName());
1✔
150
        sb.append(" other = ("); //$NON-NLS-1$
1✔
151
        sb.append(topLevelClass.getType().getShortName());
1✔
152
        sb.append(") that;"); //$NON-NLS-1$
1✔
153
        method.addBodyLine(sb.toString());
1✔
154

155
        if (useEqualsHashCodeFromRoot && topLevelClass.getSuperClass().isPresent()) {
1!
156
            method.addBodyLine("if (!super.equals(other)) {"); //$NON-NLS-1$
×
157
            method.addBodyLine("return false;"); //$NON-NLS-1$
×
158
            method.addBodyLine("}"); //$NON-NLS-1$
×
159
        }
160

161
        boolean first = true;
1✔
162
        Iterator<IntrospectedColumn> iter = introspectedColumns.iterator();
1✔
163
        while (iter.hasNext()) {
1✔
164
            IntrospectedColumn introspectedColumn = iter.next();
1✔
165

166
            sb.setLength(0);
1✔
167

168
            if (first) {
1✔
169
                sb.append("return ("); //$NON-NLS-1$
1✔
170
                first = false;
1✔
171
            } else {
172
                getIndenter().javaIndent(sb, 1);
1✔
173
                sb.append("&& ("); //$NON-NLS-1$
1✔
174
            }
175

176
            String getterMethod = getGetterMethodName(
1✔
177
                    introspectedColumn.getJavaProperty(), introspectedColumn
1✔
178
                            .getFullyQualifiedJavaType());
1✔
179

180
            if (introspectedColumn.getFullyQualifiedJavaType().isPrimitive()) {
1✔
181
                sb.append("this."); //$NON-NLS-1$
1✔
182
                sb.append(getterMethod);
1✔
183
                sb.append("() == "); //$NON-NLS-1$
1✔
184
                sb.append("other."); //$NON-NLS-1$
1✔
185
                sb.append(getterMethod);
1✔
186
                sb.append("())"); //$NON-NLS-1$
1✔
187
            } else if (introspectedColumn.getFullyQualifiedJavaType().isArray()) {
1✔
188
                topLevelClass.addImportedType("java.util.Arrays"); //$NON-NLS-1$
1✔
189
                sb.append("Arrays.equals(this."); //$NON-NLS-1$
1✔
190
                sb.append(getterMethod);
1✔
191
                sb.append("(), "); //$NON-NLS-1$
1✔
192
                sb.append("other."); //$NON-NLS-1$
1✔
193
                sb.append(getterMethod);
1✔
194
                sb.append("()))"); //$NON-NLS-1$
1✔
195
            } else {
196
                sb.append("this."); //$NON-NLS-1$
1✔
197
                sb.append(getterMethod);
1✔
198
                sb.append("() == null ? other."); //$NON-NLS-1$
1✔
199
                sb.append(getterMethod);
1✔
200
                sb.append("() == null : this."); //$NON-NLS-1$
1✔
201
                sb.append(getterMethod);
1✔
202
                sb.append("().equals(other."); //$NON-NLS-1$
1✔
203
                sb.append(getterMethod);
1✔
204
                sb.append("()))"); //$NON-NLS-1$
1✔
205
            }
206

207
            if (!iter.hasNext()) {
1✔
208
                sb.append(';');
1✔
209
            }
210

211
            method.addBodyLine(sb.toString());
1✔
212
        }
1✔
213

214
        topLevelClass.addMethod(method);
1✔
215
    }
1✔
216

217
    /**
218
     * Generates a <code>hashCode</code> method that includes all fields.
219
     *
220
     * <p>Note that this implementation is based on the eclipse foundation hashCode
221
     * generator.
222
     *
223
     * @param topLevelClass
224
     *            the class to which the method will be added
225
     * @param introspectedColumns
226
     *            column definitions of this class and any superclass of this
227
     *            class
228
     * @param introspectedTable
229
     *            the table corresponding to this class
230
     */
231
    protected void generateHashCode(TopLevelClass topLevelClass,
232
            List<IntrospectedColumn> introspectedColumns,
233
            IntrospectedTable introspectedTable) {
234
        Method method = new Method("hashCode"); //$NON-NLS-1$
1✔
235
        method.setVisibility(JavaVisibility.PUBLIC);
1✔
236
        method.setReturnType(FullyQualifiedJavaType.getIntInstance());
1✔
237
        method.addAnnotation("@Override"); //$NON-NLS-1$
1✔
238

239
        getCommentGenerator().addGeneralMethodAnnotation(method, introspectedTable, topLevelClass.getImportedTypes());
1✔
240

241
        method.addBodyLine("final int prime = 31;"); //$NON-NLS-1$
1✔
242
        method.addBodyLine("int result = 1;"); //$NON-NLS-1$
1✔
243

244
        if (useEqualsHashCodeFromRoot && topLevelClass.getSuperClass().isPresent()) {
1!
245
            method.addBodyLine("result = prime * result + super.hashCode();"); //$NON-NLS-1$
×
246
        }
247

248
        StringBuilder sb = new StringBuilder();
1✔
249
        boolean hasTemp = false;
1✔
250
        for (IntrospectedColumn introspectedColumn : introspectedColumns) {
1✔
251
            FullyQualifiedJavaType fqjt = introspectedColumn.getFullyQualifiedJavaType();
1✔
252
            String getterMethod = getGetterMethodName(introspectedColumn.getJavaProperty(), fqjt);
1✔
253

254
            sb.setLength(0);
1✔
255
            if (fqjt.isPrimitive()) {
1✔
256
                switch (fqjt.getFullyQualifiedName()) {
1!
257
                case "boolean": //$NON-NLS-1$
258
                    sb.append("result = prime * result + ("); //$NON-NLS-1$
1✔
259
                    sb.append(getterMethod);
1✔
260
                    sb.append("() ? 1231 : 1237);"); //$NON-NLS-1$
1✔
261
                    method.addBodyLine(sb.toString());
1✔
262
                    break;
1✔
263
                case "byte", "char", "int", "short": //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
264
                    sb.append("result = prime * result + "); //$NON-NLS-1$
1✔
265
                    sb.append(getterMethod);
1✔
266
                    sb.append("();"); //$NON-NLS-1$
1✔
267
                    method.addBodyLine(sb.toString());
1✔
268
                    break;
1✔
269
                case "double": //$NON-NLS-1$
270
                    if (!hasTemp) {
×
271
                        method.addBodyLine("long temp;"); //$NON-NLS-1$
×
272
                        hasTemp = true;
×
273
                    }
274
                    sb.append("temp = Double.doubleToLongBits("); //$NON-NLS-1$
×
275
                    sb.append(getterMethod);
×
276
                    sb.append("());"); //$NON-NLS-1$
×
277
                    method.addBodyLine(sb.toString());
×
278
                    method.addBodyLine("result = prime * result + (int) (temp ^ (temp >>> 32));"); //$NON-NLS-1$
×
279
                    break;
×
280
                case "float": //$NON-NLS-1$
281
                    sb.append("result = prime * result + Float.floatToIntBits("); //$NON-NLS-1$
×
282
                    sb.append(getterMethod);
×
283
                    sb.append("());"); //$NON-NLS-1$
×
284
                    method.addBodyLine(sb.toString());
×
285
                    break;
×
286
                case "long": //$NON-NLS-1$
287
                    sb.append("result = prime * result + (int) ("); //$NON-NLS-1$
×
288
                    sb.append(getterMethod);
×
289
                    sb.append("() ^ ("); //$NON-NLS-1$
×
290
                    sb.append(getterMethod);
×
291
                    sb.append("() >>> 32));"); //$NON-NLS-1$
×
292
                    method.addBodyLine(sb.toString());
×
293
                    break;
×
294
                default:
295
                    // all bases are covered above
296
                    break;
297
                }
1✔
298
            } else if (fqjt.isArray()) {
1✔
299
                // Arrays is already imported by the generateEquals method, we don't need
300
                // to do it again
301
                sb.append("result = prime * result + (Arrays.hashCode("); //$NON-NLS-1$
1✔
302
                sb.append(getterMethod);
1✔
303
                sb.append("()));"); //$NON-NLS-1$
1✔
304
                method.addBodyLine(sb.toString());
1✔
305
            } else {
306
                sb.append("result = prime * result + (("); //$NON-NLS-1$
1✔
307
                sb.append(getterMethod);
1✔
308
                sb.append("() == null) ? 0 : "); //$NON-NLS-1$
1✔
309
                sb.append(getterMethod);
1✔
310
                sb.append("().hashCode());"); //$NON-NLS-1$
1✔
311
                method.addBodyLine(sb.toString());
1✔
312
            }
313
        }
1✔
314

315
        method.addBodyLine("return result;"); //$NON-NLS-1$
1✔
316

317
        topLevelClass.addMethod(method);
1✔
318
    }
1✔
319
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc