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

mybatis / generator / 1942

12 Jan 2026 05:01PM UTC coverage: 88.75% (+0.4%) from 88.365%
1942

push

github

web-flow
Merge pull request #1412 from jeffgbutler/jspecify

Adopt JSpecify

2331 of 3162 branches covered (73.72%)

1800 of 1949 new or added lines in 202 files covered. (92.36%)

18 existing lines in 10 files now uncovered.

11384 of 12827 relevant lines covered (88.75%)

0.89 hits per line

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

82.51
/core/mybatis-generator-core/src/main/java/org/mybatis/generator/config/TableConfiguration.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.config;
17

18
import static org.mybatis.generator.internal.util.StringUtility.composeFullyQualifiedTableName;
19
import static org.mybatis.generator.internal.util.StringUtility.isTrue;
20
import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;
21

22
import java.util.ArrayList;
23
import java.util.Collections;
24
import java.util.HashMap;
25
import java.util.List;
26
import java.util.Map;
27
import java.util.Objects;
28
import java.util.Optional;
29

30
import org.jspecify.annotations.Nullable;
31
import org.mybatis.generator.internal.util.messages.Messages;
32

33
public class TableConfiguration extends PropertyHolder {
34
    private final boolean insertStatementEnabled;
35
    private final boolean selectByPrimaryKeyStatementEnabled;
36
    private final boolean selectByExampleStatementEnabled;
37
    private final boolean updateByPrimaryKeyStatementEnabled;
38
    private final boolean deleteByPrimaryKeyStatementEnabled;
39
    private final boolean deleteByExampleStatementEnabled;
40
    private final boolean countByExampleStatementEnabled;
41
    private final boolean updateByExampleStatementEnabled;
42
    private final List<ColumnOverride> columnOverrides;
43
    // this is a Map for validation purposes. Initially, all items will be FALSE. When accessed, an item will
44
    // be made TRUE. This allows us to generate warning for columns configured to be ignored but not found.
45
    private final Map<IgnoredColumn, Boolean> ignoredColumns;
46
    private final @Nullable GeneratedKey generatedKey;
47
    private final @Nullable String selectByPrimaryKeyQueryId;
48
    private final @Nullable String selectByExampleQueryId;
49
    private final @Nullable String catalog;
50
    private final @Nullable String schema;
51
    private final String tableName;
52
    private final @Nullable String domainObjectName;
53
    private final @Nullable String alias;
54
    private final ModelType modelType;
55
    private final boolean wildcardEscapingEnabled;
56
    private final boolean delimitIdentifiers;
57
    private final @Nullable DomainObjectRenamingRule domainObjectRenamingRule;
58
    private final @Nullable ColumnRenamingRule columnRenamingRule;
59
    private final boolean isAllColumnDelimitingEnabled;
60
    private final @Nullable String mapperName;
61
    private final @Nullable String sqlProviderName;
62
    private final List<IgnoredColumnPattern> ignoredColumnPatterns;
63

64
    protected TableConfiguration(Builder builder) {
65
        super(builder);
1✔
66

67
        catalog = builder.catalog;
1✔
68
        schema = builder.schema;
1✔
69
        tableName = Objects.requireNonNull(builder.tableName);
1✔
70
        domainObjectName = builder.domainObjectName;
1✔
71
        alias = builder.alias;
1✔
72
        modelType = Objects.requireNonNull(builder.modelType);
1✔
73
        insertStatementEnabled = builder.insertStatementEnabled;
1✔
74
        selectByPrimaryKeyStatementEnabled = builder.selectByPrimaryKeyStatementEnabled;
1✔
75
        selectByExampleStatementEnabled = builder.selectByExampleStatementEnabled;
1✔
76
        updateByPrimaryKeyStatementEnabled = builder.updateByPrimaryKeyStatementEnabled;
1✔
77
        deleteByPrimaryKeyStatementEnabled = builder.deleteByPrimaryKeyStatementEnabled;
1✔
78
        deleteByExampleStatementEnabled = builder.deleteByExampleStatementEnabled;
1✔
79
        countByExampleStatementEnabled = builder.countByExampleStatementEnabled;
1✔
80
        updateByExampleStatementEnabled = builder.updateByExampleStatementEnabled;
1✔
81
        wildcardEscapingEnabled = builder.wildcardEscapingEnabled;
1✔
82
        delimitIdentifiers = builder.delimitIdentifiers;
1✔
83
        isAllColumnDelimitingEnabled = builder.isAllColumnDelimitingEnabled;
1✔
84
        selectByPrimaryKeyQueryId = builder.selectByPrimaryKeyQueryId;
1✔
85
        selectByExampleQueryId = builder.selectByExampleQueryId;
1✔
86
        mapperName = builder.mapperName;
1✔
87
        sqlProviderName = builder.sqlProviderName;
1✔
88
        columnOverrides = Collections.unmodifiableList(builder.columnOverrides);
1✔
89
        ignoredColumns = builder.ignoredColumns;
1✔
90
        generatedKey = builder.generatedKey;
1✔
91
        domainObjectRenamingRule = builder.domainObjectRenamingRule;
1✔
92
        columnRenamingRule = builder.columnRenamingRule;
1✔
93
        ignoredColumnPatterns = Collections.unmodifiableList(builder.ignoredColumnPatterns);
1✔
94
    }
1✔
95

96
    public boolean isDeleteByPrimaryKeyStatementEnabled() {
97
        return deleteByPrimaryKeyStatementEnabled;
1✔
98
    }
99

100
    public boolean isInsertStatementEnabled() {
101
        return insertStatementEnabled;
1✔
102
    }
103

104
    public boolean isSelectByPrimaryKeyStatementEnabled() {
105
        return selectByPrimaryKeyStatementEnabled;
1✔
106
    }
107

108
    public boolean isUpdateByPrimaryKeyStatementEnabled() {
109
        return updateByPrimaryKeyStatementEnabled;
1✔
110
    }
111

112
    public boolean isColumnIgnored(String columnName) {
113
        for (Map.Entry<IgnoredColumn, Boolean> entry : ignoredColumns.entrySet()) {
1✔
114
            if (entry.getKey().matches(columnName)) {
1✔
115
                entry.setValue(Boolean.TRUE);
1✔
116
                return true;
1✔
117
            }
118
        }
1✔
119

120
        for (IgnoredColumnPattern ignoredColumnPattern : ignoredColumnPatterns) {
1✔
121
            if (ignoredColumnPattern.matches(columnName)) {
1✔
122
                return true;
1✔
123
            }
124
        }
1✔
125

126
        return false;
1✔
127
    }
128

129
    @Override
130
    public boolean equals(Object obj) {
131
        if (this == obj) {
×
132
            return true;
×
133
        }
134

135
        if (!(obj instanceof TableConfiguration other)) {
×
136
            return false;
×
137
        }
138

139
        return Objects.equals(this.catalog, other.catalog)
×
140
                && Objects.equals(this.schema, other.schema)
×
141
                && Objects.equals(this.tableName, other.tableName);
×
142
    }
143

144
    @Override
145
    public int hashCode() {
146
        return Objects.hash(catalog, schema, tableName);
×
147
    }
148

149
    public boolean isSelectByExampleStatementEnabled() {
150
        return selectByExampleStatementEnabled;
1✔
151
    }
152

153
    /**
154
     * May return null if the column has not been overridden.
155
     *
156
     * @param columnName
157
     *            the column name
158
     * @return the column override (if any) related to this column
159
     */
160
    public Optional<ColumnOverride> getColumnOverride(String columnName) {
161
        for (ColumnOverride co : columnOverrides) {
1✔
162
            if (co.isColumnNameDelimited()) {
1✔
163
                if (columnName.equals(co.getColumnName())) {
1✔
164
                    return Optional.of(co);
1✔
165
                }
166
            } else {
167
                if (columnName.equalsIgnoreCase(co.getColumnName())) {
1✔
168
                    return Optional.of(co);
1✔
169
                }
170
            }
171
        }
1✔
172

173
        return Optional.empty();
1✔
174
    }
175

176
    public Optional<GeneratedKey> getGeneratedKey() {
177
        return Optional.ofNullable(generatedKey);
1✔
178
    }
179

180
    public Optional<String> getSelectByExampleQueryId() {
181
        return Optional.ofNullable(selectByExampleQueryId);
1✔
182
    }
183

184
    public Optional<String> getSelectByPrimaryKeyQueryId() {
185
        return Optional.ofNullable(selectByPrimaryKeyQueryId);
1✔
186
    }
187

188
    public boolean isDeleteByExampleStatementEnabled() {
189
        return deleteByExampleStatementEnabled;
1✔
190
    }
191

192
    public boolean areAnyStatementsEnabled() {
193
        return selectByExampleStatementEnabled
1!
194
                || selectByPrimaryKeyStatementEnabled || insertStatementEnabled
195
                || updateByPrimaryKeyStatementEnabled
196
                || deleteByExampleStatementEnabled
197
                || deleteByPrimaryKeyStatementEnabled
198
                || countByExampleStatementEnabled
199
                || updateByExampleStatementEnabled;
200
    }
201

202
    public @Nullable String getAlias() {
203
        return alias;
1✔
204
    }
205

206
    public @Nullable String getCatalog() {
207
        return catalog;
1✔
208
    }
209

210
    public @Nullable String getDomainObjectName() {
211
        return domainObjectName;
1✔
212
    }
213

214
    public @Nullable String getSchema() {
215
        return schema;
1✔
216
    }
217

218
    public String getTableName() {
219
        return tableName;
1✔
220
    }
221

222
    public List<ColumnOverride> getColumnOverrides() {
223
        return columnOverrides;
1✔
224
    }
225

226
    /**
227
     * Returns a List of Strings. The values are the columns
228
     * that were specified to be ignored in the table, but do not exist in the
229
     * table.
230
     *
231
     * @return a List of Strings - the columns that were improperly configured
232
     *         as ignored columns
233
     */
234
    public List<String> getIgnoredColumnsInError() {
235
        List<String> answer = new ArrayList<>();
1✔
236

237
        for (Map.Entry<IgnoredColumn, Boolean> entry : ignoredColumns.entrySet()) {
1✔
238
            if (!entry.getValue()) {
1✔
239
                answer.add(entry.getKey().getColumnName());
1✔
240
            }
241
        }
1✔
242

243
        return answer;
1✔
244
    }
245

246
    public ModelType getModelType() {
247
        return modelType;
1✔
248
    }
249

250
    public boolean isWildcardEscapingEnabled() {
251
        return wildcardEscapingEnabled;
1✔
252
    }
253

254
    @Override
255
    public String toString() {
NEW
256
        return composeFullyQualifiedTableName(catalog, schema, tableName, '.');
×
257
    }
258

259
    public boolean isDelimitIdentifiers() {
260
        return delimitIdentifiers;
1✔
261
    }
262

263
    public boolean isCountByExampleStatementEnabled() {
264
        return countByExampleStatementEnabled;
1✔
265
    }
266

267
    public boolean isUpdateByExampleStatementEnabled() {
268
        return updateByExampleStatementEnabled;
1✔
269
    }
270

271
    public void validate(List<String> errors, int listPosition) {
272
        if (!stringHasValue(tableName)) {
1!
273
            errors.add(Messages.getString(
×
274
                    "ValidationError.6", Integer.toString(listPosition))); //$NON-NLS-1$
×
275
        }
276

277
        String fqTableName = composeFullyQualifiedTableName(
1✔
278
                catalog, schema, tableName, '.');
279

280
        if (generatedKey != null) {
1✔
281
            generatedKey.validate(errors, fqTableName);
1✔
282
        }
283

284
        // when using column indexes, either both or neither query ids
285
        // should be set
286
        if (isTrue(getProperty(PropertyRegistry.TABLE_USE_COLUMN_INDEXES))
1!
287
                && selectByExampleStatementEnabled
288
                && selectByPrimaryKeyStatementEnabled) {
289
            boolean queryId1Set = stringHasValue(selectByExampleQueryId);
1✔
290
            boolean queryId2Set = stringHasValue(selectByPrimaryKeyQueryId);
1✔
291

292
            if (queryId1Set != queryId2Set) {
1!
293
                errors.add(Messages.getString("ValidationError.13", //$NON-NLS-1$
×
294
                        fqTableName));
295
            }
296
        }
297

298
        if (domainObjectRenamingRule != null) {
1✔
299
            domainObjectRenamingRule.validate(errors, fqTableName);
1✔
300
        }
301

302
        if (columnRenamingRule != null) {
1✔
303
            columnRenamingRule.validate(errors, fqTableName);
1✔
304
        }
305

306
        for (ColumnOverride columnOverride : columnOverrides) {
1✔
307
            columnOverride.validate(errors, fqTableName);
1✔
308
        }
1✔
309

310
        for (IgnoredColumn ignoredColumn : ignoredColumns.keySet()) {
1✔
311
            ignoredColumn.validate(errors, fqTableName);
1✔
312
        }
1✔
313

314
        for (IgnoredColumnPattern ignoredColumnPattern : ignoredColumnPatterns) {
1✔
315
            ignoredColumnPattern.validate(errors, fqTableName);
1✔
316
        }
1✔
317
    }
1✔
318

319
    public @Nullable DomainObjectRenamingRule getDomainObjectRenamingRule() {
320
        return domainObjectRenamingRule;
1✔
321
    }
322

323
    public Optional<ColumnRenamingRule> getColumnRenamingRule() {
324
        return Optional.ofNullable(columnRenamingRule);
1✔
325
    }
326

327
    public boolean isAllColumnDelimitingEnabled() {
328
        return isAllColumnDelimitingEnabled;
1✔
329
    }
330

331
    public @Nullable String getMapperName() {
332
        return mapperName;
1✔
333
    }
334

335
    public @Nullable String getSqlProviderName() {
336
        return sqlProviderName;
1✔
337
    }
338

339
    public @Nullable String getDynamicSqlSupportClassName() {
340
        return getProperty(PropertyRegistry.TABLE_DYNAMIC_SQL_SUPPORT_CLASS_NAME);
1✔
341
    }
342

343
    public @Nullable String getDynamicSqlTableObjectName() {
344
        return getProperty(PropertyRegistry.TABLE_DYNAMIC_SQL_TABLE_OBJECT_NAME);
1✔
345
    }
346

347
    public static class Builder extends AbstractBuilder<Builder> {
1✔
348
        private @Nullable ModelType modelType;
349
        private @Nullable String catalog;
350
        private @Nullable String schema;
351
        private @Nullable String tableName;
352
        private @Nullable String domainObjectName;
353
        private @Nullable String alias;
354
        private boolean insertStatementEnabled = true;
1✔
355
        private boolean selectByPrimaryKeyStatementEnabled = true;
1✔
356
        private boolean selectByExampleStatementEnabled = true;
1✔
357
        private boolean updateByPrimaryKeyStatementEnabled = true;
1✔
358
        private boolean deleteByPrimaryKeyStatementEnabled = true;
1✔
359
        private boolean deleteByExampleStatementEnabled = true;
1✔
360
        private boolean countByExampleStatementEnabled = true;
1✔
361
        private boolean updateByExampleStatementEnabled = true;
1✔
362
        private boolean wildcardEscapingEnabled;
363
        private boolean delimitIdentifiers;
364
        private boolean isAllColumnDelimitingEnabled;
365
        private @Nullable String selectByPrimaryKeyQueryId;
366
        private @Nullable String selectByExampleQueryId;
367
        private @Nullable String mapperName;
368
        private @Nullable String sqlProviderName;
369
        private @Nullable GeneratedKey generatedKey;
370
        private @Nullable DomainObjectRenamingRule domainObjectRenamingRule;
371
        private @Nullable ColumnRenamingRule columnRenamingRule;
372
        private final List<IgnoredColumnPattern> ignoredColumnPatterns = new ArrayList<>();
1✔
373
        private final List<ColumnOverride> columnOverrides = new ArrayList<>();
1✔
374
        private final Map<IgnoredColumn, Boolean> ignoredColumns = new HashMap<>();
1✔
375

376
        public TableConfiguration build() {
377
            return new TableConfiguration(this);
1✔
378
        }
379

380
        @Override
381
        protected Builder getThis() {
382
            return this;
1✔
383
        }
384

385
        public Builder withModelType(ModelType defaultModelType, @Nullable String tableModelType) {
386
            this.modelType = tableModelType == null ? defaultModelType : ModelType.getModelType(tableModelType);
1!
387
            return getThis();
1✔
388
        }
389

390
        public Builder withCatalog(@Nullable String catalog) {
391
            this.catalog = catalog;
1✔
392
            return this;
1✔
393
        }
394

395
        public Builder withSchema(@Nullable String schema) {
396
            this.schema = schema;
1✔
397
            return this;
1✔
398
        }
399

400
        public Builder withTableName(@Nullable String tableName) {
401
            this.tableName = tableName;
1✔
402
            return this;
1✔
403
        }
404

405
        public Builder withDomainObjectName(@Nullable String domainObjectName) {
406
            this.domainObjectName = domainObjectName;
1✔
407
            return this;
1✔
408
        }
409

410
        public Builder withAlias(@Nullable String alias) {
411
            this.alias = alias;
1✔
412
            return this;
1✔
413
        }
414

415
        @SuppressWarnings("UnusedReturnValue")
416
        public Builder withInsertStatementEnabled(boolean insertStatementEnabled) {
NEW
417
            this.insertStatementEnabled = insertStatementEnabled;
×
NEW
418
            return this;
×
419
        }
420

421
        @SuppressWarnings("UnusedReturnValue")
422
        public Builder withSelectByPrimaryKeyStatementEnabled(boolean selectByPrimaryKeyStatementEnabled) {
NEW
423
            this.selectByPrimaryKeyStatementEnabled = selectByPrimaryKeyStatementEnabled;
×
NEW
424
            return this;
×
425
        }
426

427
        @SuppressWarnings("UnusedReturnValue")
428
        public Builder withSelectByExampleStatementEnabled(boolean selectByExampleStatementEnabled) {
429
            this.selectByExampleStatementEnabled = selectByExampleStatementEnabled;
1✔
430
            return this;
1✔
431
        }
432

433
        @SuppressWarnings("UnusedReturnValue")
434
        public Builder withUpdateByPrimaryKeyStatementEnabled(boolean updateByPrimaryKeyStatementEnabled) {
NEW
435
            this.updateByPrimaryKeyStatementEnabled = updateByPrimaryKeyStatementEnabled;
×
NEW
436
            return this;
×
437
        }
438

439
        @SuppressWarnings("UnusedReturnValue")
440
        public Builder withDeleteByPrimaryKeyStatementEnabled(boolean deleteByPrimaryKeyStatementEnabled) {
NEW
441
            this.deleteByPrimaryKeyStatementEnabled = deleteByPrimaryKeyStatementEnabled;
×
NEW
442
            return this;
×
443
        }
444

445
        @SuppressWarnings("UnusedReturnValue")
446
        public Builder withDeleteByExampleStatementEnabled(boolean deleteByExampleStatementEnabled) {
NEW
447
            this.deleteByExampleStatementEnabled = deleteByExampleStatementEnabled;
×
NEW
448
            return this;
×
449
        }
450

451
        @SuppressWarnings("UnusedReturnValue")
452
        public Builder withCountByExampleStatementEnabled(boolean countByExampleStatementEnabled) {
NEW
453
            this.countByExampleStatementEnabled = countByExampleStatementEnabled;
×
NEW
454
            return this;
×
455
        }
456

457
        @SuppressWarnings("UnusedReturnValue")
458
        public Builder withUpdateByExampleStatementEnabled(boolean updateByExampleStatementEnabled) {
NEW
459
            this.updateByExampleStatementEnabled = updateByExampleStatementEnabled;
×
NEW
460
            return this;
×
461
        }
462

463
        @SuppressWarnings("UnusedReturnValue")
464
        public Builder withWildcardEscapingEnabled(boolean wildcardEscapingEnabled) {
NEW
465
            this.wildcardEscapingEnabled = wildcardEscapingEnabled;
×
NEW
466
            return this;
×
467
        }
468

469
        @SuppressWarnings("UnusedReturnValue")
470
        public Builder withDelimitIdentifiers(boolean delimitIdentifiers) {
NEW
471
            this.delimitIdentifiers = delimitIdentifiers;
×
NEW
472
            return this;
×
473
        }
474

475
        @SuppressWarnings("UnusedReturnValue")
476
        public Builder withAllColumnDelimitingEnabled(boolean isAllColumnDelimitingEnabled) {
NEW
477
            this.isAllColumnDelimitingEnabled = isAllColumnDelimitingEnabled;
×
NEW
478
            return this;
×
479
        }
480

481
        public Builder withSelectByPrimaryKeyQueryId(@Nullable String selectByPrimaryKeyQueryId) {
482
            this.selectByPrimaryKeyQueryId = selectByPrimaryKeyQueryId;
1✔
483
            return this;
1✔
484
        }
485

486
        public Builder withSelectByExampleQueryId(@Nullable String selectByExampleQueryId) {
487
            this.selectByExampleQueryId = selectByExampleQueryId;
1✔
488
            return this;
1✔
489
        }
490

491
        public Builder withMapperName(@Nullable String mapperName) {
492
            this.mapperName = mapperName;
1✔
493
            return this;
1✔
494
        }
495

496
        public Builder withSqlProviderName(@Nullable String sqlProviderName) {
497
            this.sqlProviderName = sqlProviderName;
1✔
498
            return this;
1✔
499
        }
500

501
        @SuppressWarnings("UnusedReturnValue")
502
        public Builder withGeneratedKey(@Nullable GeneratedKey generatedKey) {
503
            this.generatedKey = generatedKey;
1✔
504
            return this;
1✔
505
        }
506

507
        @SuppressWarnings("UnusedReturnValue")
508
        public Builder withDomainObjectRenamingRule(@Nullable DomainObjectRenamingRule domainObjectRenamingRule) {
509
            this.domainObjectRenamingRule = domainObjectRenamingRule;
1✔
510
            return this;
1✔
511
        }
512

513
        @SuppressWarnings("UnusedReturnValue")
514
        public Builder withColumnRenamingRule(@Nullable ColumnRenamingRule columnRenamingRule) {
515
            this.columnRenamingRule = columnRenamingRule;
1✔
516
            return this;
1✔
517
        }
518

519
        @SuppressWarnings("UnusedReturnValue")
520
        public Builder withIgnoredColumnPattern(IgnoredColumnPattern ignoredColumnPattern) {
521
            this.ignoredColumnPatterns.add(ignoredColumnPattern);
1✔
522
            return this;
1✔
523
        }
524

525
        @SuppressWarnings("UnusedReturnValue")
526
        public Builder withIgnoredColumn(IgnoredColumn ignoredColumn) {
527
            this.ignoredColumns.put(ignoredColumn, Boolean.FALSE);
1✔
528
            return this;
1✔
529
        }
530

531
        @SuppressWarnings("UnusedReturnValue")
532
        public Builder withColumnOverride(ColumnOverride columnOverride) {
533
            this.columnOverrides.add(columnOverride);
1✔
534
            return this;
1✔
535
        }
536
    }
537
}
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