View Javadoc
1   /*
2    *    Copyright 2016-2025 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.dynamic.sql.insert.render;
17  
18  import static org.mybatis.dynamic.sql.util.StringUtilities.spaceBefore;
19  
20  import java.util.Objects;
21  
22  import org.jspecify.annotations.Nullable;
23  import org.mybatis.dynamic.sql.insert.MultiRowInsertModel;
24  import org.mybatis.dynamic.sql.render.RenderingStrategy;
25  
26  public class MultiRowInsertRenderer<T> {
27  
28      private final MultiRowInsertModel<T> model;
29      private final MultiRowValuePhraseVisitor visitor;
30  
31      private MultiRowInsertRenderer(Builder<T> builder) {
32          model = Objects.requireNonNull(builder.model);
33          // the prefix is a generic format that will be resolved below with String.format(...)
34          visitor = new MultiRowValuePhraseVisitor(Objects.requireNonNull(builder.renderingStrategy),
35                  "records[%s]"); //$NON-NLS-1$
36      }
37  
38      public MultiRowInsertStatementProvider<T> render() {
39          FieldAndValueCollector collector = model.columnMappings()
40                  .map(m -> m.accept(visitor))
41                  .collect(FieldAndValueCollector.collect());
42  
43          String insertStatement = calculateInsertStatement(collector);
44  
45          return new DefaultMultiRowInsertStatementProvider.Builder<T>().withRecords(model.records())
46                  .withInsertStatement(insertStatement)
47                  .build();
48      }
49  
50      private String calculateInsertStatement(FieldAndValueCollector collector) {
51          String statementStart = InsertRenderingUtilities.calculateInsertStatementStart(model.table());
52          String columnsPhrase = collector.columnsPhrase();
53          String valuesPhrase = collector.multiRowInsertValuesPhrase(model.recordCount());
54  
55          return statementStart + spaceBefore(columnsPhrase) + spaceBefore(valuesPhrase);
56      }
57  
58      public static <T> Builder<T> withMultiRowInsertModel(MultiRowInsertModel<T> model) {
59          return new Builder<T>().withMultiRowInsertModel(model);
60      }
61  
62      public static class Builder<T> {
63          private @Nullable MultiRowInsertModel<T> model;
64          private @Nullable RenderingStrategy renderingStrategy;
65  
66          public Builder<T> withMultiRowInsertModel(MultiRowInsertModel<T> model) {
67              this.model = model;
68              return this;
69          }
70  
71          public Builder<T> withRenderingStrategy(RenderingStrategy renderingStrategy) {
72              this.renderingStrategy = renderingStrategy;
73              return this;
74          }
75  
76          public MultiRowInsertRenderer<T> build() {
77              return new MultiRowInsertRenderer<>(this);
78          }
79      }
80  }