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

mybatis / generator / 2095

13 Mar 2026 07:14PM UTC coverage: 90.125% (+0.07%) from 90.056%
2095

push

github

web-flow
Merge pull request #1465 from mybatis/renovate/maven-3.x

Update dependency maven to v3.9.14

2362 of 3125 branches covered (75.58%)

11691 of 12972 relevant lines covered (90.12%)

0.9 hits per line

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

42.31
/core/mybatis-generator-core/src/main/java/org/mybatis/generator/api/MyBatisGenerator.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.api;
17

18
import static org.mybatis.generator.internal.util.ClassloaderUtility.getCustomClassloader;
19
import static org.mybatis.generator.internal.util.messages.Messages.getString;
20

21
import java.io.BufferedWriter;
22
import java.io.File;
23
import java.io.IOException;
24
import java.io.OutputStream;
25
import java.io.OutputStreamWriter;
26
import java.nio.charset.Charset;
27
import java.nio.file.Files;
28
import java.nio.file.Path;
29
import java.nio.file.StandardOpenOption;
30
import java.sql.SQLException;
31
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.HashSet;
34
import java.util.List;
35
import java.util.Objects;
36
import java.util.Set;
37

38
import org.jspecify.annotations.Nullable;
39
import org.mybatis.generator.codegen.CalculatedContextValues;
40
import org.mybatis.generator.codegen.GenerationEngine;
41
import org.mybatis.generator.codegen.GenerationResults;
42
import org.mybatis.generator.codegen.IntrospectionEngine;
43
import org.mybatis.generator.codegen.RootClassInfo;
44
import org.mybatis.generator.config.Configuration;
45
import org.mybatis.generator.config.Context;
46
import org.mybatis.generator.exception.InternalException;
47
import org.mybatis.generator.exception.InvalidConfigurationException;
48
import org.mybatis.generator.exception.ShellException;
49
import org.mybatis.generator.internal.DefaultShellCallback;
50
import org.mybatis.generator.internal.ObjectFactory;
51
import org.mybatis.generator.merge.java.JavaFileMerger;
52
import org.mybatis.generator.merge.java.JavaMergerFactory;
53
import org.mybatis.generator.merge.xml.XmlFileMergerJaxp;
54

55
/**
56
 * This class is the main interface to MyBatis generator. A typical execution of the tool involves these steps:
57
 * <ol>
58
 * <li>Create a Configuration object. The Configuration can be the result of a parsing the XML configuration file, or it
59
 * can be created solely in Java.</li>
60
 * <li>Create a MyBatisGenerator object</li>
61
 * <li>Call one of the generate() methods</li>
62
 * </ol>
63
 *
64
 * @author Jeff Butler
65
 *
66
 * @see org.mybatis.generator.config.xml.ConfigurationParser
67
 */
68
public class MyBatisGenerator {
69
    private static final ProgressCallback NULL_PROGRESS_CALLBACK = new ProgressCallback() { };
1✔
70
    private final Configuration configuration;
71
    private final ShellCallback shellCallback;
72
    private final ProgressCallback progressCallback;
73
    private final Set<String> contextIds;
74
    private final Set<String> fullyQualifiedTableNames;
75
    private final JavaFileMerger javaFileMerger;
76
    private final boolean isOverwriteEnabled;
77
    private final boolean isJavaFileMergeEnabled;
78

79
    private final List<GenerationResults> generationResultsList = new ArrayList<>();
1✔
80

81
    private MyBatisGenerator(Builder builder) {
1✔
82
        configuration = Objects.requireNonNull(builder.configuration, getString("RuntimeError.2")); //$NON-NLS-1$
1✔
83
        shellCallback = Objects.requireNonNullElseGet(builder.shellCallback, DefaultShellCallback::new);
1✔
84
        progressCallback = Objects.requireNonNullElse(builder.progressCallback, NULL_PROGRESS_CALLBACK);
1✔
85
        fullyQualifiedTableNames = builder.fullyQualifiedTableNames;
1✔
86
        contextIds = builder.contextIds;
1✔
87

88
        if (builder.isJavaFileMergeEnabled) {
1!
89
            isJavaFileMergeEnabled = true;
×
90
            javaFileMerger = JavaMergerFactory.getMerger(JavaMergerFactory.PrinterConfiguration.LEXICAL_PRESERVING);
×
91
        } else {
92
            isJavaFileMergeEnabled = false;
1✔
93
            javaFileMerger = (newContent, existingContent) -> newContent;
1✔
94
        }
95

96
        isOverwriteEnabled = builder.isOverwriteEnabled;
1✔
97
    }
1✔
98

99
    /**
100
     * This is one of the main methods for generating code. This method is long-running, but progress can be provided
101
     * and the method can be canceled through the ProgressCallback interface. This method will not write results to
102
     * the disk. The generated objects can be retrieved from the getGeneratedJavaFiles(), getGeneratedKotlinFiles(),
103
     * getGeneratedXmlFiles(), and getGeneratedGenericFiles() methods.
104
     *
105
     * @return any warnings created during the generation process
106
     * @throws SQLException
107
     *             the SQL exception
108
     * @throws InterruptedException
109
     *             if the method is canceled through the ProgressCallback
110
     * @throws InvalidConfigurationException
111
     *             if the specified configuration is invalid
112
     */
113
    public List<String> generateOnly() throws SQLException, InterruptedException, InvalidConfigurationException {
114
        List<String> warnings = new ArrayList<>();
1✔
115
        generateFiles(warnings);
1✔
116
        progressCallback.done();
1✔
117
        return warnings;
1✔
118
    }
119

120
    /**
121
     * This is one of the main methods for generating code. This method is long-running, but progress can be provided
122
     * and the method can be canceled through the ProgressCallback interface. This method will write results to
123
     * the disk.
124
     *
125
     * @return any warnings created during the generation process
126
     * @throws SQLException
127
     *             the SQL exception
128
     * @throws IOException
129
     *             Signals that an I/O exception has occurred.
130
     * @throws InterruptedException
131
     *             if the method is canceled through the ProgressCallback
132
     * @throws InvalidConfigurationException
133
     *             if the specified configuration is invalid
134
     */
135
    public List<String> generateAndWrite() throws SQLException, IOException, InterruptedException,
136
            InvalidConfigurationException {
137
        List<String> warnings = new ArrayList<>();
×
138
        generateFiles(warnings);
×
139
        writeGeneratedFiles(warnings);
×
140
        progressCallback.done();
×
141
        return warnings;
×
142
    }
143

144
    private void generateFiles(List<String> warnings) throws SQLException, InterruptedException,
145
            InvalidConfigurationException {
146
        configuration.validate();
1✔
147
        generationResultsList.clear();
1✔
148
        ObjectFactory.reset();
1✔
149
        RootClassInfo.reset();
1✔
150

151
        setupCustomClassloader();
1✔
152
        List<Context> contextsToRun = calculateContextsToRun();
1✔
153
        List<CalculatedContextValues> contextValuesList = calculateContextValues(contextsToRun, warnings);
1✔
154
        List<ContextValuesAndTables> contextValuesAndTablesList = runAllIntrospections(contextValuesList, warnings);
1✔
155
        List<GenerationEngine> generationEngines = createGenerationEngines(contextValuesAndTablesList, warnings);
1✔
156
        runGenerationEngines(generationEngines);
1✔
157
    }
1✔
158

159
    private void setupCustomClassloader() {
160
        if (!configuration.getClassPathEntries().isEmpty()) {
1!
161
            ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries());
×
162
            ObjectFactory.addExternalClassLoader(classLoader);
×
163
        }
164
    }
1✔
165

166
    private List<Context> calculateContextsToRun() {
167
        List<Context> contextsToRun;
168
        if (fullyQualifiedTableNames.isEmpty()) {
1!
169
            contextsToRun = configuration.getContexts();
1✔
170
        } else {
171
            contextsToRun = configuration.getContexts().stream()
×
172
                    .filter(c -> contextIds.contains(c.getId()))
×
173
                    .toList();
×
174
        }
175

176
        return contextsToRun;
1✔
177
    }
178

179
    private List<CalculatedContextValues> calculateContextValues(List<Context> contextsToRun, List<String> warnings) {
180
        return contextsToRun.stream()
1✔
181
                .map(c -> createContextValues(c, warnings))
1✔
182
                .toList();
1✔
183
    }
184

185
    private CalculatedContextValues createContextValues(Context context, List<String> warnings) {
186
        return new CalculatedContextValues.Builder()
1✔
187
                .withContext(context)
1✔
188
                .withWarnings(warnings)
1✔
189
                .build();
1✔
190
    }
191

192
    private List<ContextValuesAndTables> runAllIntrospections(List<CalculatedContextValues> contextValuesList,
193
                                                              List<String> warnings)
194
            throws SQLException, InterruptedException {
195
        int totalSteps = contextValuesList.stream()
1✔
196
                .map(CalculatedContextValues::context)
1✔
197
                .mapToInt(Context::getIntrospectionSteps)
1✔
198
                .sum();
1✔
199
        progressCallback.introspectionStarted(totalSteps);
1✔
200

201
        List<ContextValuesAndTables> contextValuesAndTablesList = new ArrayList<>();
1✔
202
        for (CalculatedContextValues contextValues : contextValuesList) {
1✔
203
            contextValuesAndTablesList.add(new ContextValuesAndTables(contextValues,
1✔
204
                    runContextIntrospection(fullyQualifiedTableNames, contextValues, warnings)));
1✔
205
        }
1✔
206

207
        return contextValuesAndTablesList;
1✔
208
    }
209

210
    private List<IntrospectedTable> runContextIntrospection(Set<String> fullyQualifiedTableNames,
211
                                                            CalculatedContextValues contextValues,
212
                                                            List<String> warnings)
213
            throws SQLException, InterruptedException {
214
        return new IntrospectionEngine.Builder()
1✔
215
                .withContextValues(contextValues)
1✔
216
                .withFullyQualifiedTableNames(fullyQualifiedTableNames)
1✔
217
                .withWarnings(warnings)
1✔
218
                .withProgressCallback(progressCallback)
1✔
219
                .build()
1✔
220
                .introspectTables();
1✔
221
    }
222

223
    private List<GenerationEngine> createGenerationEngines(List<ContextValuesAndTables> contextValuesAndTablesListList,
224
                                                           List<String> warnings) {
225
        return contextValuesAndTablesListList.stream()
1✔
226
                .map(c -> createGenerationEngine(c, warnings))
1✔
227
                .toList();
1✔
228
    }
229

230
    private GenerationEngine createGenerationEngine(ContextValuesAndTables contextValuesAndTables,
231
                                                    List<String> warnings) {
232
        return new GenerationEngine.Builder()
1✔
233
                .withContextValues(contextValuesAndTables.contextValues())
1✔
234
                .withProgressCallback(progressCallback)
1✔
235
                .withWarnings(warnings)
1✔
236
                .withIntrospectedTables(contextValuesAndTables.introspectedTables())
1✔
237
                .build();
1✔
238
    }
239

240
    private void runGenerationEngines(List<GenerationEngine> generationEngines) throws InterruptedException {
241
        // calculate the number of steps
242
        int totalSteps = generationEngines.stream().mapToInt(GenerationEngine::getGenerationSteps).sum();
1✔
243
        progressCallback.generationStarted(totalSteps);
1✔
244

245
        // now run the generators
246
        for (GenerationEngine generationEngine: generationEngines) {
1✔
247
            var generationResults = generationEngine.generate();
1✔
248
            generationResultsList.add(generationResults);
1✔
249
        }
1✔
250
    }
1✔
251

252
    private void writeGeneratedFiles(List<String> warnings) throws IOException, InterruptedException {
253
        Set<String> projects = new HashSet<>();
×
254
        int totalSteps = generationResultsList.stream().mapToInt(GenerationResults::getNumberOfGeneratedFiles).sum();
×
255
        progressCallback.saveStarted(totalSteps);
×
256

257
        for (GenerationResults generationResults : generationResultsList) {
×
258
            for (GeneratedXmlFile gxf : generationResults.generatedXmlFiles()) {
×
259
                projects.add(gxf.getTargetProject());
×
260
                writeGeneratedXmlFile(gxf, generationResults.xmlFormatter(), warnings);
×
261
            }
×
262

263
            for (GeneratedJavaFile gjf : generationResults.generatedJavaFiles()) {
×
264
                projects.add(gjf.getTargetProject());
×
265
                writeGeneratedJavaFile(gjf, generationResults.javaFormatter(), generationResults.javaFileEncoding(),
×
266
                        warnings);
267
            }
×
268

269
            for (GeneratedKotlinFile gkf : generationResults.generatedKotlinFiles()) {
×
270
                projects.add(gkf.getTargetProject());
×
271
                writeGeneratedKotlinFile(gkf, generationResults.kotlinFormatter(),
×
272
                        generationResults.kotlinFileEncoding(), warnings);
×
273
            }
×
274

275
            for (GenericGeneratedFile gf : generationResults.generatedGenericFiles()) {
×
276
                projects.add(gf.getTargetProject());
×
277
                writeGenericGeneratedFile(gf, warnings);
×
278
            }
×
279
        }
×
280

281
        for (String project : projects) {
×
282
            shellCallback.refreshProject(project);
×
283
        }
×
284
    }
×
285

286
    private void writeGeneratedJavaFile(GeneratedJavaFile gjf, JavaFormatter javaFormatter,
287
                                        @Nullable String javaFileEncoding, List<String> warnings)
288
            throws InterruptedException, IOException {
289
        Path targetFile;
290
        String source = javaFormatter.getFormattedContent(gjf.getCompilationUnit());
×
291
        try {
292
            File directory = shellCallback.getDirectory(gjf.getTargetProject(), gjf.getTargetPackage());
×
293
            targetFile = directory.toPath().resolve(gjf.getFileName());
×
294
            if (Files.exists(targetFile)) {
×
295
                if (isJavaFileMergeEnabled) {
×
296
                    source = javaFileMerger.getMergedSource(source, targetFile.toFile(), javaFileEncoding);
×
297
                } else if (isOverwriteEnabled) {
×
298
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
299
                } else {
300
                    targetFile = getUniqueFileName(directory, gjf.getFileName());
×
301
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
302
                }
303
            }
304

305
            progressCallback.checkCancel();
×
306
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
307
            writeFile(targetFile.toFile(), source, javaFileEncoding);
×
308
        } catch (ShellException e) {
×
309
            warnings.add(e.getMessage());
×
310
        }
×
311
    }
×
312

313
    private void writeGeneratedKotlinFile(GeneratedKotlinFile gf, KotlinFormatter kotlinFormatter,
314
                                          @Nullable String kotlinFileEncoding, List<String> warnings)
315
            throws InterruptedException, IOException {
316
        Path targetFile;
317
        String source = kotlinFormatter.getFormattedContent(gf.getKotlinFile());
×
318
        try {
319
            File directory = shellCallback.getDirectory(gf.getTargetProject(), gf.getTargetPackage());
×
320
            targetFile = directory.toPath().resolve(gf.getFileName());
×
321
            if (Files.exists(targetFile)) {
×
322
                if (isOverwriteEnabled) {
×
323
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
324
                } else {
325
                    targetFile = getUniqueFileName(directory, gf.getFileName());
×
326
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
327
                }
328
            }
329

330
            progressCallback.checkCancel();
×
331
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
332
            writeFile(targetFile.toFile(), source, kotlinFileEncoding);
×
333
        } catch (ShellException e) {
×
334
            warnings.add(e.getMessage());
×
335
        }
×
336
    }
×
337

338
    private void writeGenericGeneratedFile(GenericGeneratedFile gf, List<String> warnings)
339
            throws InterruptedException, IOException {
340
        Path targetFile;
341
        String source = gf.getFormattedContent();
×
342
        try {
343
            File directory = shellCallback.getDirectory(gf.getTargetProject(), gf.getTargetPackage());
×
344
            targetFile = directory.toPath().resolve(gf.getFileName());
×
345
            if (Files.exists(targetFile)) {
×
346
                if (isOverwriteEnabled) {
×
347
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
348
                } else {
349
                    targetFile = getUniqueFileName(directory, gf.getFileName());
×
350
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
351
                }
352
            }
353

354
            progressCallback.checkCancel();
×
355
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
356
            writeFile(targetFile.toFile(), source, gf.getFileEncoding().orElse(null));
×
357
        } catch (ShellException e) {
×
358
            warnings.add(e.getMessage());
×
359
        }
×
360
    }
×
361

362
    private void writeGeneratedXmlFile(GeneratedXmlFile gxf, XmlFormatter xmlFormatter, List<String> warnings)
363
            throws InterruptedException, IOException {
364
        Path targetFile;
365
        String source = xmlFormatter.getFormattedContent(gxf.getDocument());
×
366
        try {
367
            File directory = shellCallback.getDirectory(gxf.getTargetProject(), gxf.getTargetPackage());
×
368
            targetFile = directory.toPath().resolve(gxf.getFileName());
×
369
            if (Files.exists(targetFile)) {
×
370
                if (gxf.isMergeable()) {
×
371
                    source = XmlFileMergerJaxp.getMergedSource(source, targetFile.toFile());
×
372
                } else if (isOverwriteEnabled) {
×
373
                    warnings.add(getString("Warning.11", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
374
                } else {
375
                    targetFile = getUniqueFileName(directory, gxf.getFileName());
×
376
                    warnings.add(getString("Warning.2", targetFile.toFile().getAbsolutePath())); //$NON-NLS-1$
×
377
                }
378
            }
379

380
            progressCallback.checkCancel();
×
381
            progressCallback.startTask(getString("Progress.15", targetFile.toString())); //$NON-NLS-1$
×
382
            writeFile(targetFile.toFile(), source, "UTF-8"); //$NON-NLS-1$
×
383
        } catch (ShellException e) {
×
384
            warnings.add(e.getMessage());
×
385
        }
×
386
    }
×
387

388
    /**
389
     * Writes, or overwrites, the contents of the specified file.
390
     *
391
     * @param file
392
     *            the file
393
     * @param content
394
     *            the content
395
     * @param fileEncoding
396
     *            the file encoding
397
     * @throws IOException
398
     *             Signals that an I/O exception has occurred.
399
     */
400
    private void writeFile(File file, String content, @Nullable String fileEncoding) throws IOException {
401
        try (OutputStream fos = Files.newOutputStream(file.toPath(), StandardOpenOption.CREATE,
×
402
                StandardOpenOption.TRUNCATE_EXISTING)) {
403
            OutputStreamWriter osw;
404
            if (fileEncoding == null) {
×
405
                osw = new OutputStreamWriter(fos);
×
406
            } else {
407
                osw = new OutputStreamWriter(fos, Charset.forName(fileEncoding));
×
408
            }
409

410
            try (BufferedWriter bw = new BufferedWriter(osw)) {
×
411
                bw.write(content);
×
412
            }
413
        }
414
    }
×
415

416
    /**
417
     * Gets the unique file name.
418
     *
419
     * @param directory
420
     *            the directory
421
     * @param fileName
422
     *            the file name
423
     * @return the unique file name
424
     */
425
    private Path getUniqueFileName(File directory, String fileName) {
426
        Path answer = null;
×
427

428
        // try up to 1000 times to generate a unique file name
429
        StringBuilder sb = new StringBuilder();
×
430
        for (int i = 1; i < 1000; i++) {
×
431
            sb.setLength(0);
×
432
            sb.append(fileName);
×
433
            sb.append('.');
×
434
            sb.append(i);
×
435

436
            Path testFile = directory.toPath().resolve(sb.toString());
×
437
            if (Files.notExists(testFile)) {
×
438
                answer = testFile;
×
439
                break;
×
440
            }
441
        }
442

443
        if (answer == null) {
×
444
            throw new InternalException(getString("RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$
×
445
        }
446

447
        return answer;
×
448
    }
449

450
    /**
451
     * Returns the list of generated Java files after a call to one of the generate methods.
452
     * This is useful if you prefer to process the generated files yourself and do not want
453
     * the generator to write them to disk.
454
     *
455
     * @return the list of generated Java files
456
     */
457
    public List<GeneratedJavaFile> getGeneratedJavaFiles() {
458
        return generationResultsList.stream()
1✔
459
                .map(GenerationResults::generatedJavaFiles)
1✔
460
                .flatMap(Collection::stream)
1✔
461
                .toList();
1✔
462
    }
463

464
    /**
465
     * Returns the list of generated Kotlin files after a call to one of the generate methods.
466
     * This is useful if you prefer to process the generated files yourself and do not want
467
     * the generator to write them to disk.
468
     *
469
     * @return the list of generated Kotlin files
470
     */
471
    public List<GeneratedKotlinFile> getGeneratedKotlinFiles() {
472
        return generationResultsList.stream()
1✔
473
                .map(GenerationResults::generatedKotlinFiles)
1✔
474
                .flatMap(Collection::stream)
1✔
475
                .toList();
1✔
476
    }
477

478
    /**
479
     * Returns the list of generated XML files after a call to one of the generate methods.
480
     * This is useful if you prefer to process the generated files yourself and do not want
481
     * the generator to write them to disk.
482
     *
483
     * @return the list of generated XML files
484
     */
485
    public List<GeneratedXmlFile> getGeneratedXmlFiles() {
486
        return generationResultsList.stream()
1✔
487
                .map(GenerationResults::generatedXmlFiles)
1✔
488
                .flatMap(Collection::stream)
1✔
489
                .toList();
1✔
490
    }
491

492
    /**
493
     * Returns the list of generated generic files after a call to one of the generate methods.
494
     * This is useful if you prefer to process the generated files yourself and do not want
495
     * the generator to write them to disk.
496
     *
497
     * <p>The list will be empty unless you have used a plugin that generates generic files
498
     * or are using a custom runtime.
499
     *
500
     * @return the list of generated generic files
501
     */
502
    public List<GenericGeneratedFile> getGeneratedGenericFiles() {
503
        return generationResultsList.stream()
×
504
                .map(GenerationResults::generatedGenericFiles)
×
505
                .flatMap(Collection::stream)
×
506
                .toList();
×
507
    }
508

509
    private record ContextValuesAndTables(CalculatedContextValues contextValues,
1✔
510
                                          List<IntrospectedTable> introspectedTables) { }
511

512
    public static class Builder {
1✔
513
        private @Nullable Configuration configuration;
514
        private @Nullable ShellCallback shellCallback;
515
        private @Nullable ProgressCallback progressCallback;
516
        private final Set<String> contextIds = new HashSet<>();
1✔
517
        private final Set<String> fullyQualifiedTableNames = new HashSet<>();
1✔
518
        private boolean isOverwriteEnabled = false;
1✔
519
        private boolean isJavaFileMergeEnabled = false;
1✔
520

521
        public Builder withConfiguration(Configuration configuration) {
522
            this.configuration = configuration;
1✔
523
            return this;
1✔
524
        }
525

526
        public Builder withShellCallback(ShellCallback shellCallback) {
527
            this.shellCallback = shellCallback;
1✔
528
            return this;
1✔
529
        }
530

531
        public Builder withProgressCallback(@Nullable ProgressCallback progressCallback) {
532
            this.progressCallback = progressCallback;
×
533
            return this;
×
534
        }
535

536
        /**
537
         * Set of context IDs to use in generation. Only the contexts with an id specified in this set will run.
538
         * If the set is empty, then all contexts are run.
539
         *
540
         * @param contextIds
541
         *            a set of contextIds to use in code generation
542
         *
543
         * @return this builder
544
         */
545
        public Builder withContextIds(Set<String> contextIds) {
546
            this.contextIds.addAll(contextIds);
×
547
            return this;
×
548
        }
549

550
        /**
551
         *  Set of table names to generate. The elements of the set must be Strings that exactly match what's
552
         *  specified in the configuration. For example, if a table name = "foo" and schema = "bar", then the fully
553
         *  qualified table name is "foo.bar". If the Set is empty, then all tables in the configuration
554
         *  will be used for code generation.
555
         *
556
         * @param fullyQualifiedTableNames
557
         *            a set of table names to use in code generation
558
         *
559
         * @return this builder
560
         */
561
        public Builder withFullyQualifiedTableNames(Set<String> fullyQualifiedTableNames) {
562
            this.fullyQualifiedTableNames.addAll(fullyQualifiedTableNames);
×
563
            return this;
×
564
        }
565

566
        /**
567
         * If true, then newly generated files will overwrite existing files if there is a collision.
568
         * If false, then newly generated files will be written with a unique name when there is a collision.
569
         *
570
         * <p>The default is <code>false</code></p>
571
         *
572
         * @param overwriteEnabled where newly generated files should overwrite existing files if there is a collision
573
         * @return this builder
574
         */
575
        public Builder withOverwriteEnabled(boolean overwriteEnabled) {
576
            this.isOverwriteEnabled = overwriteEnabled;
1✔
577
            return this;
1✔
578
        }
579

580
        /**
581
         * If true, then newly generated Java files will be merged if they collide with existing files.
582
         * If false, then the {@link #withOverwriteEnabled(boolean)} value governs what happens on a collision.
583
         *
584
         * <p>The default is <code>false</code></p>
585
         *
586
         * @param javaFileMergeEnabled where the Java file merger support should be enabled
587
         * @return this builder
588
         */
589
        public Builder withJavaFileMergeEnabled(boolean javaFileMergeEnabled) {
590
            this.isJavaFileMergeEnabled = javaFileMergeEnabled;
×
591
            return this;
×
592
        }
593

594
        public MyBatisGenerator build() {
595
            return new MyBatisGenerator(this);
1✔
596
        }
597
    }
598
}
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