Skip to content

Commit 1e6b73e

Browse files
committed
Update documentation
1 parent 9169596 commit 1e6b73e

File tree

3 files changed

+115
-77
lines changed

3 files changed

+115
-77
lines changed

src/site/markdown/docs/mybatis3.md

Lines changed: 107 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Specialized Support for MyBatis3
22
Most of the examples shown on this site are for usage with MyBatis3 - even though the library does support other SQL runtimes like Spring JDBC templates. In addition to the examples shown elsewhere, the library has additional specialized support for MyBatis3 beyond what is shown in the other examples. This support mainly exists to support MyBatis Generator and the code generated by that tool. Even without MyBatis Generator, some of the techniques shown on this page may prove useful.
33

4-
This support is added to the DELETE, SELECT, and UPDATE statement generators and enables the creating of reusable methods as delivered in MyBatis Generator. These methods can provide some boilerplate code for the setup of the statement (a column list and table name for example), and allow the user to specify a where clause.
4+
The goal of this support is to reduce the amount of boilerplate code needed for a typical CRUD mapper. For example, this support allows you to create a reusable SELECT method where the user only needs to specify a WHERE clause.
55

6-
With version 1.1.3, specialized interfaces were added that can further simplify client code. This support enables the creation of methods that have similar functionality to some of the methods generated in previous versions of MyBatis generator like countByExample, deleteByExample, and selectByExample. We no longer use the "by example" terms for these methods as this library has eliminated the Example class that was generated by prior versions of MyBatis generator.
6+
With version 1.1.3, specialized interfaces and utilities were added that can further simplify client code. This support enables the creation of methods that have similar functionality to some of the methods generated in previous versions of MyBatis generator like countByExample, deleteByExample, and selectByExample. We no longer use the "by example" terms for these methods as this library has eliminated the Example class that was generated by prior versions of MyBatis generator.
77

88
## Count Method Support
99

@@ -19,25 +19,22 @@ long count(SelectStatementProvider selectStatement);
1919
This is a standard method for MyBatis Dynamic SQL that executes a query and returns a `long`. The second method will reuse this method and supply everything needed to build the select statement except the where clause:
2020

2121
```java
22-
default long count(MyBatis3CountHelper helper) {
23-
return helper.apply(SelectDSL.selectWithMapper(this::count, SqlBuilder.count())
24-
.from(simpleTable))
25-
.build()
26-
.execute();
22+
default long count(MyBatis3SelectCompleter completer) {
23+
return MyBatis3Utils.count(this::count, person, completer);
2724
}
2825
```
2926

30-
This method shows the use of `MyBatis3CountHelper` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause. Clients can use the method as follows:
27+
This method shows the use of `MyBatis3SelectCompleter` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause. Clients can use the method as follows:
3128

3229
```java
33-
long rows = mapper.count(h ->
34-
h.where(occupation, isNull()));
30+
long rows = mapper.count(c ->
31+
c.where(occupation, isNull()));
3532
```
3633

3734
There is a utility method that can be used to count all rows in a table:
3835

3936
```java
40-
long rows = mapper.count(MyBatis3CountHelper.allRows());
37+
long rows = mapper.count(MyBatis3SelectCompleter.allRows());
4138
```
4239

4340
## Delete Method Support
@@ -54,26 +51,74 @@ int delete(DeleteStatementProvider deleteStatement);
5451
This is a standard method for MyBatis Dynamic SQL that executes a delete and returns an `int` - the number of rows deleted. The second method will reuse this method and supply everything needed to build the delete statement except the where clause:
5552

5653
```java
57-
default int delete(MyBatis3DeleteHelper helper) {
58-
return helper.apply(MyBatis3Utils.deleteFrom(this::delete, simpleTable))
59-
.build()
60-
.execute();
54+
default int delete(MyBatis3DeleteCompleter completer) {
55+
return MyBatis3Utils.deleteFrom(this::delete, person, completer);
6156
}
6257
```
6358

64-
This method shows the use of `MyBatis3DeleteHelper` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause. Clients can use the method as follows:
59+
This method shows the use of `MyBatis3DeleteCompleter` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause. Clients can use the method as follows:
6560

6661
```java
67-
int rows = mapper.delete(h ->
68-
h.where(occupation, isNull()));
62+
int rows = mapper.delete(c ->
63+
c.where(occupation, isNull()));
6964
```
7065

7166
There is a utility method that can be used to delete all rows in a table:
7267

7368
```java
74-
int rows = mapper.delete(MyBatis3DeleteHelper.allRows());
69+
int rows = mapper.delete(MyBatis3DeleteCompleter.allRows());
7570
```
7671

72+
## Insert Method Support
73+
74+
The goal of insert method support is to remove some of the boilerplate code from insert methods in a mapper interfaces.
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:
77+
78+
```java
79+
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
80+
int insert(InsertStatementProvider<PersonRecord> insertStatement);
81+
82+
@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple")
83+
int insertMultiple(MultiRowInsertStatementProvider<PersonRecord> insertStatement);
84+
```
85+
86+
These two methods are standard methods for MyBatis Dynamic SQL. They execute a single row insert and a multiple row insert.
87+
88+
These methods can be used to implement simplified insert methods:
89+
90+
```java
91+
default int insert(PersonRecord record) {
92+
return MyBatis3Utils.insert(this::insert, record, person, c ->
93+
c.map(id).toProperty("id")
94+
.map(firstName).toProperty("firstName")
95+
.map(lastName).toProperty("lastName")
96+
.map(birthDate).toProperty("birthDate")
97+
.map(employed).toProperty("employed")
98+
.map(occupation).toProperty("occupation")
99+
.map(addressId).toProperty("addressId")
100+
);
101+
}
102+
103+
default int insertMultiple(PersonRecord...records) {
104+
return insertMultiple(Arrays.asList(records));
105+
}
106+
107+
default int insertMultiple(Collection<PersonRecord> records) {
108+
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, person, c ->
109+
c.map(id).toProperty("id")
110+
.map(firstName).toProperty("firstName")
111+
.map(lastName).toProperty("lastName")
112+
.map(birthDate).toProperty("birthDate")
113+
.map(employed).toProperty("employed")
114+
.map(occupation).toProperty("occupation")
115+
.map(addressId).toProperty("addressId")
116+
);
117+
}
118+
```
119+
120+
In the mapper, only the column mappings need to be specified and no other boilerplate code is needed.
121+
77122
## Select Method Support
78123

79124
The goal of select method support is to enable the creation of methods that execute a select statement allowing a user to specify a where clause and/or order by clause at runtime, but abstracting away all other details.
@@ -82,89 +127,84 @@ To use this support, we envision creating several methods on a MyBatis mapper in
82127

83128
```java
84129
@SelectProvider(type=SqlProviderAdapter.class, method="select")
85-
@Results(id="SimpleTableResult", value= {
130+
@Results(id="PersonResult", value= {
86131
@Result(column="A_ID", property="id", jdbcType=JdbcType.INTEGER, id=true),
87132
@Result(column="first_name", property="firstName", jdbcType=JdbcType.VARCHAR),
88133
@Result(column="last_name", property="lastName", jdbcType=JdbcType.VARCHAR),
89134
@Result(column="birth_date", property="birthDate", jdbcType=JdbcType.DATE),
90135
@Result(column="employed", property="employed", jdbcType=JdbcType.VARCHAR),
91136
@Result(column="occupation", property="occupation", jdbcType=JdbcType.VARCHAR)
92137
})
93-
List<SimpleTableRecord> selectMany(SelectStatementProvider selectStatement);
138+
List<PersonRecord> selectMany(SelectStatementProvider selectStatement);
94139

95140
@SelectProvider(type=SqlProviderAdapter.class, method="select")
96-
@ResultMap("SimpleTableResult")
97-
Optional<SimpleTableRecord> selectOne(SelectStatementProvider selectStatement);
141+
@ResultMap("PersonResult")
142+
Optional<PersonRecord> selectOne(SelectStatementProvider selectStatement);
98143
```
99144

100145
These two methods are standard methods for MyBatis Dynamic SQL. They execute a select and return either a list of records, or a single record.
101146

147+
We also envision creating a static field for a reusable list of columns for a select statement:
148+
149+
```java
150+
static BasicColumn[] selectList =
151+
new BasicColumn[] {id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId};
152+
```
153+
102154
The `selectOne` method can be used to implement a generalized select one method:
103155

104156
```java
105-
default Optional<SimpleTableRecord> selectOne(MyBatis3SelectOneHelper<SimpleTableRecord> helper) {
106-
return helper.apply(SelectDSL.selectWithMapper(this::selectOne, id.as("A_ID"), firstName, lastName, birthDate, employed, occupation)
107-
.from(simpleTable))
108-
.build()
109-
.execute();
157+
default Optional<PersonRecord> selectOne(MyBatis3SelectCompleter completer) {
158+
return MyBatis3Utils.selectOne(this::selectOne, selectList, person, completer);
110159
}
111160
```
112161

113-
This method shows the use of `MyBatis3SelectOneHelper` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause.
162+
This method shows the use of `MyBatis3SelectCompleter` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause.
114163

115164
The general `selectOne` method can be used to implement a `selectByPrimaryKey` method:
116165

117166
```java
118-
default Optional<SimpleTableRecord> selectByPrimaryKey(Integer id_) {
119-
return selectOne(h ->
120-
h.where(id, isEqualTo(id_))
167+
default Optional<PersonRecord> selectByPrimaryKey(Integer id_) {
168+
return selectOne(c ->
169+
c.where(id, isEqualTo(id_))
121170
);
122171
}
123172
```
124173

125174
The `selectMany` method can be used to implement generalized select methods where a user can specify a where clause and/or an order by clause. Typically we recommend two of these methods - for select, and select distinct:
126175

127176
```java
128-
default List<SimpleTableRecord> select(MyBatis3SelectListHelper<SimpleTableRecord> helper) {
129-
return helper.apply(SelectDSL.selectWithMapper(this::selectMany, id.as("A_ID"), firstName, lastName, birthDate,
130-
employed, occupation)
131-
.from(simpleTable))
132-
.build()
133-
.execute();
177+
default List<PersonRecord> select(MyBatis3SelectCompleter completer) {
178+
return MyBatis3Utils.selectList(this::selectMany, selectList, person, completer);
134179
}
135180

136-
default List<SimpleTableRecord> selectDistinct(MyBatis3SelectListHelper<SimpleTableRecord> helper) {
137-
return helper.apply(SelectDSL.selectDistinctWithMapper(this::selectMany, id.as("A_ID"), firstName, lastName,
138-
birthDate, employed, occupation)
139-
.from(simpleTable))
140-
.build()
141-
.execute();
181+
default List<PersonRecord> selectDistinct(MyBatis3SelectCompleter completer) {
182+
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, person, completer);
142183
}
143184
```
144185

145-
146186
These methods show the use of `MyBatis3SelectListHelper` which is a specialization of a `java.util.Function` that will allow a user to supply a where clause and/or an order by clause.
147187

148188
Clients can use the methods as follows:
149189

150190
```java
151-
List<SimpleTableRecord> rows = mapper.select(h ->
152-
h.where(id, isEqualTo(1))
191+
List<PersonRecord> rows = mapper.select(c ->
192+
c.where(id, isEqualTo(1))
153193
.or(occupation, isNull()));
154194
```
155195

156196
There are utility methods that will select all rows in a table:
157197

158198
```java
159-
List<SimpleTableRecord> rows =
160-
mapper.selectByExample(MyBatis3SelectListHelper.allRows());
199+
List<PersonRecord> rows =
200+
mapper.selectByExample(MyBatis3SelectCompleter.allRows());
161201
```
162202

163203
The following query will select all rows in a specified order:
164204

165205
```java
166-
List<SimpleTableRecord> rows =
167-
mapper.selectByExample(MyBatis3SelectListHelper.allRowsOrderedBy(lastName, firstName));
206+
List<PersonRecord> rows =
207+
mapper.selectByExample(MyBatis3SelectCompleter.allRowsOrderedBy(lastName, firstName));
168208
```
169209

170210
## Update Method Support
@@ -181,33 +221,31 @@ int update(UpdateStatementProvider updateStatement);
181221
This is a standard method for MyBatis Dynamic SQL that executes a query and returns an `int` - the number of rows updated. The second method will reuse this method and supply everything needed to build the update statement except the values and the where clause:
182222

183223
```java
184-
default int update(MyBatis3UpdateHelper helper) {
185-
return helper.apply(MyBatis3Utils.update(this::update, simpleTable))
186-
.build()
187-
.execute();
224+
default int update(MyBatis3UpdateCompleter completer) {
225+
return MyBatis3Utils.update(this::update, person, completer);
188226
}
189227
```
190228

191-
This method shows the use of `MyBatis3UpdateHelper` which is a specialization of a `java.util.Function` that will allow a user to supply values and a where clause. Clients can use the method as follows:
229+
This method shows the use of `MyBatis3UpdateCompleter` which is a specialization of a `java.util.Function` that will allow a user to supply values and a where clause. Clients can use the method as follows:
192230

193231
```java
194-
int rows = mapper.update(h ->
195-
h.set(occupation).equalTo("Programmer")
232+
int rows = mapper.update(c ->
233+
c.set(occupation).equalTo("Programmer")
196234
.where(id, isEqualTo(100)));
197235
```
198236

199237
All rows in a table can be updated by simply omitting the where clause:
200238

201239
```java
202-
int rows = mapper.update(h ->
203-
h.set(occupation).equalTo("Programmer"));
240+
int rows = mapper.update(c ->
241+
c.set(occupation).equalTo("Programmer"));
204242
```
205243

206244
It is also possible to write a utility method that will set values. For example:
207245

208246
```java
209-
static UpdateDSL<MyBatis3UpdateModelAdapter<Integer>> setSelective(SimpleTableRecord record,
210-
UpdateDSL<MyBatis3UpdateModelAdapter<Integer>> dsl) {
247+
static UpdateDSL<UpdateModel> setSelective(PersonRecord record,
248+
UpdateDSL<UpdateModel> dsl) {
211249
return dsl.set(id).equalToWhenPresent(record::getId)
212250
.set(firstName).equalToWhenPresent(record::getFirstName)
213251
.set(lastName).equalToWhenPresent(record::getLastName)
@@ -226,12 +264,12 @@ rows = mapper.update(h ->
226264
```
227265

228266
# Prior Support
229-
Prior to version 1.1.3, it was also possible to write reusable methods, but they were a bit inconsistent with other helper methods.
267+
Prior to version 1.1.3, it was also possible to write reusable methods, but they were a bit inconsistent with other helper methods. Mappers of this style are deprecated and the support classes for mappers of this style will be removed in a future version of this library.
230268

231269
For example, it is possible to write a mapper interface like this:
232270

233271
```java
234-
import static examples.simple.SimpleTableDynamicSqlSupport.*;
272+
import static examples.simple.PersonDynamicSqlSupport.*;
235273

236274
import java.util.List;
237275

@@ -247,20 +285,20 @@ import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
247285
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
248286

249287
@Mapper
250-
public interface SimpleTableMapper {
288+
public interface LegacyPersonMapper {
251289

252290
@SelectProvider(type=SqlProviderAdapter.class, method="select")
253-
@Results(id="SimpleTableResult", value= {
291+
@Results(id="PersonResult", value= {
254292
@Result(column="A_ID", property="id", jdbcType=JdbcType.INTEGER, id=true),
255293
@Result(column="first_name", property="firstName", jdbcType=JdbcType.VARCHAR),
256294
@Result(column="last_name", property="lastName", jdbcType=JdbcType.VARCHAR),
257295
@Result(column="birth_date", property="birthDate", jdbcType=JdbcType.DATE),
258296
@Result(column="employed", property="employed", jdbcType=JdbcType.VARCHAR, typeHandler=YesNoTypeHandler.class),
259297
@Result(column="occupation", property="occupation", jdbcType=JdbcType.VARCHAR)
260298
})
261-
List<SimpleTableRecord> selectMany(SelectStatementProvider selectStatement);
299+
List<PersonRecord> selectMany(SelectStatementProvider selectStatement);
262300

263-
default QueryExpressionDSL<MyBatis3SelectModelAdapter<List<SimpleTableRecord>>> selectByExample() {
301+
default QueryExpressionDSL<MyBatis3SelectModelAdapter<List<PersonRecord>>> selectByExample() {
264302
return SelectDSL.selectWithMapper(this::selectMany, id.as("A_ID"), firstName, lastName, birthDate, employed, occupation)
265303
.from(simpleTable);
266304
}
@@ -272,7 +310,7 @@ Notice the `selectByExample` method - it specifies the column list and table nam
272310
The code is used like this:
273311

274312
```java
275-
List<SimpleTableRecord> rows = mapper.selectByExample()
313+
List<PersonRecord> rows = mapper.selectByExample()
276314
.where(id, isEqualTo(1))
277315
.or(occupation, isNull())
278316
.build()

src/test/java/examples/simple/PersonMapper.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public interface PersonMapper {
6868
int insertMultiple(MultiRowInsertStatementProvider<PersonRecord> insertStatement);
6969

7070
@SelectProvider(type=SqlProviderAdapter.class, method="select")
71-
@Results(id="SimpleTableResult", value= {
71+
@Results(id="PersonResult", value= {
7272
@Result(column="A_ID", property="id", jdbcType=JdbcType.INTEGER, id=true),
7373
@Result(column="first_name", property="firstName", jdbcType=JdbcType.VARCHAR),
7474
@Result(column="last_name", property="lastName", jdbcType=JdbcType.VARCHAR, typeHandler=LastNameTypeHandler.class),
@@ -80,9 +80,12 @@ public interface PersonMapper {
8080
List<PersonRecord> selectMany(SelectStatementProvider selectStatement);
8181

8282
@SelectProvider(type=SqlProviderAdapter.class, method="select")
83-
@ResultMap("SimpleTableResult")
83+
@ResultMap("PersonResult")
8484
Optional<PersonRecord> selectOne(SelectStatementProvider selectStatement);
8585

86+
static BasicColumn[] selectList =
87+
new BasicColumn[] {id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId};
88+
8689
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
8790
int update(UpdateStatementProvider updateStatement);
8891

@@ -140,9 +143,6 @@ default int insertSelective(PersonRecord record) {
140143
);
141144
}
142145

143-
static BasicColumn[] selectList =
144-
new BasicColumn[] {id.as("A_ID"), firstName, lastName, birthDate, employed, occupation, addressId};
145-
146146
default Optional<PersonRecord> selectOne(MyBatis3SelectCompleter completer) {
147147
return MyBatis3Utils.selectOne(this::selectOne, selectList, person, completer);
148148
}

src/test/java/examples/simple/legacy/LegacyPersonMapper.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public interface LegacyPersonMapper {
6767
int update(UpdateStatementProvider updateStatement);
6868

6969
@SelectProvider(type=SqlProviderAdapter.class, method="select")
70-
@Results(id="SimpleTableResult", value= {
70+
@Results(id="PersonResult", value= {
7171
@Result(column="A_ID", property="id", jdbcType=JdbcType.INTEGER, id=true),
7272
@Result(column="first_name", property="firstName", jdbcType=JdbcType.VARCHAR),
7373
@Result(column="last_name", property="lastName", jdbcType=JdbcType.VARCHAR, typeHandler=LastNameTypeHandler.class),
@@ -79,11 +79,11 @@ public interface LegacyPersonMapper {
7979
List<PersonRecord> selectMany(SelectStatementProvider selectStatement);
8080

8181
@SelectProvider(type=SqlProviderAdapter.class, method="select")
82-
@ResultMap("SimpleTableResult")
82+
@ResultMap("PersonResult")
8383
List<PersonRecord> selectManyWithRowbounds(SelectStatementProvider selectStatement, RowBounds rowBounds);
8484

8585
@SelectProvider(type=SqlProviderAdapter.class, method="select")
86-
@ResultMap("SimpleTableResult")
86+
@ResultMap("PersonResult")
8787
PersonRecord selectOne(SelectStatementProvider selectStatement);
8888

8989
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")

0 commit comments

Comments
 (0)