View Javadoc
1   /*
2    *    Copyright 2016-2024 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.render;
17  
18  import java.util.concurrent.atomic.AtomicInteger;
19  
20  import org.mybatis.dynamic.sql.BindableColumn;
21  
22  /**
23   * A rendering strategy is used to generate a platform specific binding.
24   *
25   * <p>Rendering strategies are used during the rendering phase of statement generation.
26   * All generated SQL statements include the generated statement itself, and a map of parameters that
27   * should be bound to the statement at execution time. For example, a generated select statement may
28   * look like this when rendered for MyBatis:
29   *
30   * <p><code>select foo from bar where id = #{parameters.p1,jdbcType=INTEGER}</code>
31   *
32   * <p>In this case, the binding is <code>#{parameters.p1,jdbcType=INTEGER}</code>. MyBatis knows how to interpret this
33   * binding - it will look for a value in the <code>parameters.p1</code> property of the parameter object
34   * passed to the statement and bind it as a prepared statement parameter when executing the statement.
35   */
36  public abstract class RenderingStrategy {
37      public static final String DEFAULT_PARAMETER_PREFIX = "parameters"; //$NON-NLS-1$
38  
39      public String formatParameterMapKey(AtomicInteger sequence) {
40          return "p" + sequence.getAndIncrement(); //$NON-NLS-1$
41      }
42  
43      /**
44       * This method generates a binding for a parameter to a placeholder in a generated SQL statement.
45       *
46       * <p>This binding is appropriate when there can be a mapping between a parameter and a known target column,
47       * In MyBatis, the binding can specify type information based on the column. The bindings are specific
48       * to the target framework.
49       *
50       * <p>For MyBatis, a binding looks like this: "#{prefix.parameterName,jdbcType=xxx,typeHandler=xxx,javaType=xxx}"
51       *
52       * <p>For Spring, a binding looks like this: ":parameterName"
53       *
54       * @param column column definition used for generating type details in a MyBatis binding. Ignored for Spring.
55       * @param prefix parameter prefix used for locating the parameters in a SQL provider object. Typically, will be
56       *               {@link RenderingStrategy#DEFAULT_PARAMETER_PREFIX}. This is ignored for Spring.
57       * @param parameterName name of the parameter. Typically generated by calling
58       *     {@link RenderingStrategy#formatParameterMapKey(AtomicInteger)}
59       * @return the generated binding
60       */
61      public abstract String getFormattedJdbcPlaceholder(BindableColumn<?> column, String prefix, String parameterName);
62  
63      /**
64       * This method generates a binding for a parameter to a placeholder in a generated SQL statement.
65       *
66       * <p>This binding is appropriate when the parameter is bound to placeholder that is not a known column (such as
67       * a limit or offset parameter). The bindings are specific to the target framework.
68       *
69       * <p>For MyBatis, a binding looks like this: "#{prefix.parameterName}"
70       *
71       * <p>For Spring, a binding looks like this: ":parameterName"
72       *
73       * @param prefix parameter prefix used for locating the parameters in a SQL provider object. Typically, will be
74       *               {@link RenderingStrategy#DEFAULT_PARAMETER_PREFIX}. This is ignored for Spring.
75       * @param parameterName name of the parameter. Typically generated by calling
76       *     {@link RenderingStrategy#formatParameterMapKey(AtomicInteger)}
77       * @return the generated binding
78       */
79      public abstract String getFormattedJdbcPlaceholder(String prefix, String parameterName);
80  
81      /**
82       * This method generates a binding for a parameter to a placeholder in a row based insert statement.
83       *
84       * <p>This binding is specifically for use with insert, batch insert, and multirow insert statements.
85       * These statements bind parameters to properties of a row class. The Spring implementation changes the binding
86       * to match values expected for a these insert statements. For MyBatis, the binding is the same
87       * as {@link RenderingStrategy#getFormattedJdbcPlaceholder(BindableColumn, String, String)}.
88       *
89       * <p>For MyBatis, a binding looks like this: "#{prefix.parameterName,jdbcType=xxx,typeHandler=xxx,javaType=xxx}"
90       *
91       * <p>For Spring, a binding looks like this: ":prefix.parameterName"
92       *
93       * @param column column definition used for generating type details in a MyBatis binding. Ignored for Spring.
94       * @param prefix parameter prefix used for locating the parameters in a SQL provider object. Typically, will be
95       *     either "row" or "records[x]" to match the properties of the generated statement object class.
96       * @param parameterName name of the parameter. Typically, this is a property in the row class associated with the
97       *     insert statement.
98       * @return the generated binding
99       */
100     public String getRecordBasedInsertBinding(BindableColumn<?> column, String prefix, String parameterName) {
101         return getFormattedJdbcPlaceholder(column, prefix, parameterName);
102     }
103 
104     /**
105      * This method generates a binding for a parameter to a placeholder in a row based insert statement.
106      *
107      * <p>This binding is specifically for use with insert, batch insert, and multirow insert statements and the
108      * MapToRow mapping. These statements bind parameters to the row class directly.
109      *
110      * <p>For MyBatis, a binding looks like this: "#{parameterName,jdbcType=xxx,typeHandler=xxx,javaType=xxx}"
111      *
112      * <p>For Spring, a binding looks like this: ":parameterName"
113      *
114      * @param column column definition used for generating type details in a MyBatis binding. Ignored for Spring.
115      * @param parameterName name of the parameter. Typically, will be
116      *     either "row" or "records[x]" to match the properties of the generated statement object class.
117      * @return the generated binding
118      */
119     public abstract String getRecordBasedInsertBinding(BindableColumn<?> column, String parameterName);
120 }