You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Added a general insert statement that does not require a separate record class to hold values for the insert. ([#201](https://github.com/mybatis/mybatis-dynamic-sql/issues/201))
Copy file name to clipboardExpand all lines: src/site/markdown/docs/insert.md
+62-1Lines changed: 62 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,8 @@ The library will generate a variety of INSERT statements:
4
4
1. An insert for a single record
5
5
1. An insert for multiple records with a single statement
6
6
1. An insert for multiple records with a JDBC batch
7
-
2. An insert with a select statement
7
+
1. A general insert statement
8
+
1. An insert with a select statement
8
9
9
10
## Single Record Insert
10
11
A single record insert is a statement that inserts a single record into a table. This statement is configured differently than other statements in the library so that MyBatis' support for generated keys will work properly. To use the statement, you must first create an object that will map to the database row, then map object attributes to fields in the database. For example:
@@ -213,6 +214,66 @@ It is important to open a MyBatis session by setting the executor type to BATCH.
213
214
214
215
Notice that the same mapper method that is used to insert a single record is now executed multiple times. The `map` methods are the same with the exception that the `toPropertyWhenPresent` mapping is not supported for batch inserts.
215
216
217
+
## General Insert Statement
218
+
A general insert is used to build arbitrary insert statements. The general insert does not require a separate record object o hold values for the statement - any value can be passed into the statement. This version of the insert is not convienient for retriving generated keys with MyBatis - for that use case we recommend the "single record insert". However the general insert is perfectly acceptible for Spring JDBC template or MyBatis inserts that do not return generated keys. For example
Notice the `set` method. It is used to set the value for a database column. There are several different possibilities:
231
+
232
+
1.`set(column).toNull()` will insert a null into a column
233
+
2.`set(column).toConstant(constant_value)` will insert a constant into a column. The constant_value will be written into the generated insert statement exactly as entered
234
+
3.`set(column).toStringConstant(constant_value)` will insert a constant into a column. The constant_value will be written into the generated insert statement surrounded by single quote marks (as an SQL String)
235
+
4.`set(column).toValue(value)` will insert a value into a column. The value of the property will be bound to the SQL statement as a prepared statement parameter
236
+
5.`set(column).toValueWhenPresent(property, Supplier<?> valueSupplier)` will insert a value into a column if the value is non-null. The value of the property will be bound to the SQL statement as a prepared statement parameter.
237
+
238
+
### Annotated Mapper for General Insert Statements
239
+
The GeneralInsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you
240
+
are using an annotated mapper, the insert method should look like this:
int generalInsert(GeneralInsertStatementProvider insertStatement);
250
+
...
251
+
252
+
```
253
+
254
+
### XML Mapper for General Insert Statements
255
+
We do not recommend using an XML mapper for insert statements, but if you want to do so the GeneralInsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly.
256
+
257
+
If you are using an XML mapper, the insert method should look like this in the Java interface:
Insert method support enables the removal of some of the boilerplate code from insert methods in a mapper interfaces.
154
154
155
-
To use this support, we envision creating several methods - two standard mapper methods, and other extension methods. The standard mapper methods are standard MyBatis Dynamic SQL methods that will execute a delete:
155
+
To use this support, we envision creating several methods - both standard mapper methods, and other extension methods. The standard mapper methods are standard MyBatis Dynamic SQL methods that will execute an insert:
fun PersonMapper.insertMultiple(varargrecords:PersonRecord) =
183
189
insertMultiple(records.toList())
184
190
@@ -205,7 +211,7 @@ fun PersonMapper.insertSelective(record: PersonRecord) =
205
211
}
206
212
```
207
213
208
-
Note these methods use Kotlin utility methods named `insert`and `insertMultiple`. Both methods accept a function with a receiver that will allow column mappings. The methods will build and execute insert statements.= with the supplied column mappings.
214
+
Note these methods use Kotlin utility methods named `insert`, `insertInto`, and `insertMultiple`. Those methods accept a function with a receiver that will allow column mappings. The methods will build and execute insert statements with the supplied column mappings.
209
215
210
216
Clients use these methods as follows:
211
217
@@ -214,6 +220,17 @@ Clients use these methods as follows:
214
220
val record =PersonRecord(100, "Joe", LastName("Jones"), Date(), true, "Developer", 1)
215
221
val rows = mapper.insert(record)
216
222
223
+
// general insert...
224
+
val rows = mapper.insert {
225
+
set(id).toValue(100)
226
+
set(firstName).toValue("Joe")
227
+
set(lastName).toValue(LastName("Jones"))
228
+
set(employed).toValue(true)
229
+
set(occupation).toValue("Developer")
230
+
set(addressId).toValue(1)
231
+
set(birthDate).toValue(Date())
232
+
}
233
+
217
234
// multiple insert...
218
235
val record1 =PersonRecord(100, "Joe", LastName("Jones"), Date(), true, "Developer", 1)
219
236
val record2 =PersonRecord(101, "Sarah", LastName("Smith"), Date(), true, "Architect", 2)
Copy file name to clipboardExpand all lines: src/site/markdown/docs/kotlinSpring.md
+46-3Lines changed: 46 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,9 +101,9 @@ There is also an extention method that can be used to count all rows in a table:
101
101
}
102
102
```
103
103
104
-
## Insert Method Support
104
+
## Insert Record Method Support
105
105
106
-
Insert method support enables the creation of arbitrary insert statements.
106
+
Insert method support enables the creation of arbitrary insert statements given a class that matches a database row. If you do not with to create such a class, then see the general insert support following this section.
107
107
108
108
The DSL for insert methods looks like this:
109
109
@@ -128,7 +128,7 @@ This code creates an `InsertStatementProvider` that can be executed with an exte
128
128
val rows = template.insert(insertStatement) // rows is an Int
129
129
```
130
130
131
-
This is the two step execution process. This can be combined into a single step with code like the following:
131
+
This is the two step execution process. These steps can be combined into a single step with code like the following:
132
132
133
133
```kotlin
134
134
val record =PersonRecord(100, "Joe", "Jones", Date(), "Yes", "Developer", 1)
@@ -146,6 +146,49 @@ This is the two step execution process. This can be combined into a single step
146
146
147
147
Note the use of the `toPropertyWhenPresent` mapping - this will only set the insert value if the value of the property is non null. Also note that you can use the mapping methods to map insert fields to nulls and constants if desired.
148
148
149
+
## General Insert Method Support
150
+
151
+
General insert method support enables the creation of arbitrary insert statements and does not require the creation of a class matching the database row.
152
+
153
+
The DSL for general insert methods looks like this:
154
+
155
+
```kotlin
156
+
val insertStatement = insertInto(Person) { // insertStatement is a GeneralInsertStatementProvider
157
+
set(id).toValue(100)
158
+
set(firstName).toValue("Joe")
159
+
set(lastName).toValue("Jones")
160
+
set(birthDate).toValue(Date())
161
+
set(employed).toValue("Yes")
162
+
set(occupation).toValue("Developer")
163
+
set(addressId).toValue(1)
164
+
}
165
+
```
166
+
167
+
This code creates a `GeneralInsertStatementProvider` that can be executed with an extension method for `NamedParameterJdbcTemplate` like this:
168
+
169
+
```kotlin
170
+
val template:NamedParameterJdbcTemplate= getTemplate() // not shown
171
+
val rows = template.insert(insertStatement) // rows is an Int
172
+
```
173
+
174
+
This is the two step execution process. These steps can be combined into a single step with code like the following:
175
+
176
+
```kotlin
177
+
val myOccupation ="Developer"
178
+
179
+
val rows = template.insertInto(Person) {
180
+
set(id).toValue(100)
181
+
set(firstName).toValue("Joe")
182
+
set(lastName).toValue("Jones")
183
+
set(birthDate).toValue(Date())
184
+
set(employed).toValue("Yes")
185
+
set(occupation).toValueWhenPresent(myOccupation)
186
+
set(addressId).toValue(1)
187
+
}
188
+
```
189
+
190
+
Note the use of the `toValueWhenPresent` mapping - this will only set the insert value if the value of the property is non null. Also note that you can use the mapping methods to map insert fields to nulls and constants if desired.
191
+
149
192
## Select Method Support
150
193
151
194
Select method support enables the creation of methods that execute a query allowing a user to specify a where clause and/or an order by clause and/or pagination clauses at runtime, but abstracting away all other details.
Copy file name to clipboardExpand all lines: src/site/markdown/docs/mybatis3.md
+10-3Lines changed: 10 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,21 +73,28 @@ int rows = mapper.delete(DeleteDSLCompleter.allRows());
73
73
74
74
The goal of insert method support is to remove some of the boilerplate code from insert methods in a mapper interfaces.
75
75
76
-
To use this support, we envision creating several methods on a MyBatis mapper interface. The first two methods are the standard MyBatis Dynamic SQL method that will execute an insert:
76
+
To use this support, we envision creating several methods on a MyBatis mapper interface. The first methods are the standard MyBatis methods that will execute an insert:
returnMyBatis3Utils.insert(this::insert, record, person, c ->
93
100
c.map(id).toProperty("id")
@@ -117,7 +124,7 @@ default int insertMultiple(Collection<PersonRecord> records) {
117
124
}
118
125
```
119
126
120
-
In the mapper, only the column mappings need to be specified and no other boilerplate code is needed.
127
+
The first insert method is a general insert and can be used to create arbitrary inserts with different combinations of columns specified. The other methods have the insert statements mapped to a POJO "record" class that holds values for the insert statement.
Copy file name to clipboardExpand all lines: src/site/markdown/docs/spring.md
+42-7Lines changed: 42 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ MyBatis3 is a higher level abstraction over JDBC than Spring JDBC templates. Whi
23
23
The Spring Named Parameter JDBC template expects an SQL statement with parameter markers in the Spring format, and a set of matched parameters. MyBatis Dynamic SQL will generate both. The parameters returned from the generated SQL statement can be wrapped in a Spring `MapSqlParameterSource`. Spring also expects you to provide a row mapper for creating the returned objects. The following code shows a complete example:
@@ -47,11 +47,46 @@ The Spring Named Parameter JDBC template expects an SQL statement with parameter
47
47
});
48
48
```
49
49
50
-
## Executing Insert Statements
51
-
Insert statements are a bit different - MyBatis Dynamic SQL generates a properly formatted SQL string for Spring, but instead of a map of parameters, the parameter mappings are created for the inserted record itself. So the parameters for the Spring template are created by a `BeanPropertySqlParameterSource`. Generated keys in Spring are supported with a `GeneratedKeyHolder`. The following is a complete example:
50
+
## Executing General Insert Statements
51
+
General insert statements do not require a POJO object matching a table row. Following is a complete example:
int rows = template.update(insertStatement.getInsertStatement(), insertStatement.getParameters());
64
+
```
65
+
66
+
If you want to retrieve generated keys for a general insert statement the steps are similar except that you must wrap the parameters in a `MapSqlParameterSource` object and use a `GeneratedKeyHolder`. Following is a complete example of this usage:
67
+
68
+
```java
69
+
NamedParameterJdbcTemplate template = getTemplate(); // not shown
Insert record statements are a bit different - MyBatis Dynamic SQL generates a properly formatted SQL string for Spring, but instead of a map of parameters, the parameter mappings are created for the inserted record itself. So the parameters for the Spring template are created by a `BeanPropertySqlParameterSource`. Generated keys in Spring are supported with a `GeneratedKeyHolder`. The following is a complete example:
87
+
88
+
```java
89
+
NamedParameterJdbcTemplate template = getTemplate(); // not shown
55
90
56
91
GeneratedAlwaysRecord record =newGeneratedAlwaysRecord();
57
92
record.setId(100);
@@ -77,7 +112,7 @@ Insert statements are a bit different - MyBatis Dynamic SQL generates a properly
77
112
Batch insert support in Spring is a bit different than batch support in MyBatis3 and Spring does not support returning generated keys from a batch insert. The following is a complete example of a batch insert (note the use of `SqlParameterSourceUtils` to create an array of parameter sources from an array of input records):
0 commit comments