Skip to content

Commit 2a06692

Browse files
committed
Documentation Updates
1 parent dc4a7eb commit 2a06692

File tree

10 files changed

+261
-196
lines changed

10 files changed

+261
-196
lines changed

src/site/markdown/docs/mybatis3.md

+56-85
Large diffs are not rendered by default.

src/site/markdown/docs/quickStart.md

+117-75
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,38 @@ Working with MyBatis Dynamic SQL requires the following steps:
99
For the purposes of this discussion, we will show using the library to perform CRUD operations on this table:
1010

1111
```sql
12-
create table SimpleTable (
13-
id int not null,
14-
first_name varchar(30) not null,
15-
last_name varchar(30) not null,
16-
birth_date date not null,
17-
employed varchar(3) not null,
18-
occupation varchar(30) null,
19-
primary key(id)
12+
create table Person (
13+
id int not null,
14+
first_name varchar(30) not null,
15+
last_name varchar(30) not null,
16+
birth_date date not null,
17+
employed varchar(3) not null,
18+
occupation varchar(30) null,
19+
address_id int not null,
20+
primary key(id)
2021
);
2122
```
2223

24+
We will also create a simple Java class to represent a row in the table:
25+
26+
```java
27+
package examples.simple;
28+
29+
import java.util.Date;
30+
31+
public class PersonRecord {
32+
private Integer id;
33+
private String firstName;
34+
private LastName lastName;
35+
private Date birthDate;
36+
private Boolean employed;
37+
private String occupation;
38+
private Integer addressId;
39+
40+
// getters and setters omitted
41+
}
42+
```
43+
2344
## Defining Tables and Columns
2445

2546
The class `org.mybatis.dynamic.sql.SqlTable` is used to define a table. A table definition includes
@@ -36,8 +57,8 @@ A column definition includes:
3657
4. (optional) The name of a type handler to use in MyBatis if the default type handler is not desired
3758

3859
We suggest the following usage pattern to give maximum flexibility. This pattern will allow you to use your
39-
table and columns in a "qualified" or "un-qualified" manner that looks like natural SQL. For example, in the
40-
following a column could be referred to as `firstName` or `simpleTable.firstName`.
60+
table and column names in a "qualified" or "un-qualified" manner that looks like natural SQL. For example, in the
61+
following a column could be referred to as `firstName` or `person.firstName`.
4162

4263
```java
4364
package examples.simple;
@@ -48,109 +69,130 @@ import java.util.Date;
4869
import org.mybatis.dynamic.sql.SqlColumn;
4970
import org.mybatis.dynamic.sql.SqlTable;
5071

51-
public final class SimpleTableDynamicSqlSupport {
52-
public static final SimpleTable simpleTable = new SimpleTable();
53-
public static final SqlColumn<Integer> id = simpleTable.id;
54-
public static final SqlColumn<String> firstName = simpleTable.firstName;
55-
public static final SqlColumn<String> lastName = simpleTable.lastName;
56-
public static final SqlColumn<Date> birthDate = simpleTable.birthDate;
57-
public static final SqlColumn<Boolean> employed = simpleTable.employed;
58-
public static final SqlColumn<String> occupation = simpleTable.occupation;
59-
60-
public static final class SimpleTable extends SqlTable {
72+
public final class PersonDynamicSqlSupport {
73+
public static final Person person = new Person();
74+
public static final SqlColumn<Integer> id = person.id;
75+
public static final SqlColumn<String> firstName = person.firstName;
76+
public static final SqlColumn<LastName> lastName = person.lastName;
77+
public static final SqlColumn<Date> birthDate = person.birthDate;
78+
public static final SqlColumn<Boolean> employed = person.employed;
79+
public static final SqlColumn<String> occupation = person.occupation;
80+
public static final SqlColumn<Integer> addressId = person.addressId;
81+
82+
public static final class Person extends SqlTable {
6183
public final SqlColumn<Integer> id = column("id", JDBCType.INTEGER);
6284
public final SqlColumn<String> firstName = column("first_name", JDBCType.VARCHAR);
63-
public final SqlColumn<String> lastName = column("last_name", JDBCType.VARCHAR);
85+
public final SqlColumn<LastName> lastName = column("last_name", JDBCType.VARCHAR, "examples.simple.LastNameTypeHandler");
6486
public final SqlColumn<Date> birthDate = column("birth_date", JDBCType.DATE);
6587
public final SqlColumn<Boolean> employed = column("employed", JDBCType.VARCHAR, "examples.simple.YesNoTypeHandler");
6688
public final SqlColumn<String> occupation = column("occupation", JDBCType.VARCHAR);
89+
public final SqlColumn<Integer> addressId = column("address_id", JDBCType.INTEGER);
6790

68-
public SimpleTable() {
69-
super("SimpleTable");
91+
public Person() {
92+
super("Person");
7093
}
7194
}
7295
}
7396
```
7497

7598
## Creating MyBatis3 Mappers
76-
The library will create classes that will be used as input to a MyBatis mapper. These classes include the generated SQL, as well as a parameter set that will match the generated SQL. Both are required by MyBatis. It is intended that these objects be the one and only parameter to a MyBatis mapper method.
99+
The library will create classes that will be used as input to a MyBatis mapper. These classes include the generated
100+
SQL, as well as a parameter set that will match the generated SQL. Both are required by MyBatis. It is intended that
101+
these objects be the one and only parameter to a MyBatis mapper method.
77102

78-
The library can be used with both XML and annotated mappers, but we recommend using MyBatis' annotated mapper support in all cases. The only case where XML is required is when you code a JOIN statement - in that case you will need to define your result map in XML due to limitations of the MyBatis annotations in supporting joins.
103+
The library can be used with both XML and annotated mappers, but we recommend using MyBatis' annotated mapper support in
104+
all cases. The only case where XML is required is when you code a JOIN statement - in that case you will need to define
105+
your result map in XML due to limitations of the MyBatis annotations in supporting joins.
79106

80107
For example, a mapper might look like this:
81108

82109
```java
83110
package examples.simple;
84111

85112
import java.util.List;
113+
import java.util.Optional;
86114

87-
import org.apache.ibatis.annotations.DeleteProvider;
88-
import org.apache.ibatis.annotations.InsertProvider;
89115
import org.apache.ibatis.annotations.Mapper;
90116
import org.apache.ibatis.annotations.Result;
91117
import org.apache.ibatis.annotations.ResultMap;
92118
import org.apache.ibatis.annotations.Results;
93119
import org.apache.ibatis.annotations.SelectProvider;
94-
import org.apache.ibatis.annotations.UpdateProvider;
95120
import org.apache.ibatis.type.JdbcType;
96-
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
97-
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
98121
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
99-
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
100122
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
123+
import org.mybatis.dynamic.sql.util.mybatis3.CommonCountMapper;
124+
import org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper;
125+
import org.mybatis.dynamic.sql.util.mybatis3.CommonInsertMapper;
126+
import org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper;
101127

102128
@Mapper
103-
public interface SimpleTableAnnotatedMapper {
104-
105-
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
106-
int insert(InsertStatementProvider<SimpleTableRecord> insertStatement);
107-
108-
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
109-
int update(UpdateStatementProvider updateStatement);
110-
111-
@SelectProvider(type=SqlProviderAdapter.class, method="select")
112-
@Results(id="SimpleTableResult", value= {
113-
@Result(column="A_ID", property="id", jdbcType=JdbcType.INTEGER, id=true),
114-
@Result(column="first_name", property="firstName", jdbcType=JdbcType.VARCHAR),
115-
@Result(column="last_name", property="lastName", jdbcType=JdbcType.VARCHAR),
116-
@Result(column="birth_date", property="birthDate", jdbcType=JdbcType.DATE),
117-
@Result(column="employed", property="employed", jdbcType=JdbcType.VARCHAR, typeHandler=YesNoTypeHandler.class),
118-
@Result(column="occupation", property="occupation", jdbcType=JdbcType.VARCHAR)
129+
public interface PersonMapper extends CommonCountMapper, CommonDeleteMapper, CommonInsertMapper<PersonRecord>, CommonUpdateMapper {
130+
131+
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
132+
@Results(id = "PersonResult", value = {
133+
@Result(column = "A_ID", property = "id", jdbcType = JdbcType.INTEGER, id = true),
134+
@Result(column = "first_name", property = "firstName", jdbcType = JdbcType.VARCHAR),
135+
@Result(column = "last_name", property = "lastName", jdbcType = JdbcType.VARCHAR, typeHandler = LastNameTypeHandler.class),
136+
@Result(column = "birth_date", property = "birthDate", jdbcType = JdbcType.DATE),
137+
@Result(column = "employed", property = "employed", jdbcType = JdbcType.VARCHAR, typeHandler = YesNoTypeHandler.class),
138+
@Result(column = "occupation", property = "occupation", jdbcType = JdbcType.VARCHAR),
139+
@Result(column = "address_id", property = "addressId", jdbcType = JdbcType.INTEGER)
119140
})
120-
List<SimpleTableRecord> selectMany(SelectStatementProvider selectStatement);
121-
122-
@SelectProvider(type=SqlProviderAdapter.class, method="select")
123-
@ResultMap("SimpleTableResult")
124-
SimpleTableRecord selectOne(SelectStatementProvider selectStatement);
141+
List<PersonRecord> selectMany(SelectStatementProvider selectStatement);
125142

126-
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
127-
int delete(DeleteStatementProvider deleteStatement);
128-
129-
@SelectProvider(type=SqlProviderAdapter.class, method="select")
130-
long count(SelectStatementProvider selectStatement);
143+
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
144+
@ResultMap("PersonResult")
145+
Optional<PersonRecord> selectOne(SelectStatementProvider selectStatement);
131146
}
132147
```
133148

149+
This mapper implements full CRUD functionality for the table. The base interfaces `CommonCountMapper`,
150+
`CommonDeleteMapper`, etc. provide insert, update, delete, and count capabilities. Only the select methods must be
151+
written because of the custom result map.
152+
153+
Note that the `CommonInsertMapper` interface will not properly return the generated key if one is produced by the insert.
154+
If you need generated key support, see the documentation page for INSERT statements for details on how to implement
155+
such support.
156+
134157
## Executing SQL with MyBatis3
135-
In a DAO or service class, you can use the generated statement as input to your mapper methods. Here's
136-
an example from `examples.simple.SimpleTableAnnotatedMapperTest`:
158+
In a service class, you can use the generated statement as input to your mapper methods. Here are some
159+
examples from `examples.simple.PersonMapperTest`:
137160

138161
```java
139-
@Test
140-
public void testSelectByExample() {
141-
try (SqlSession session = sqlSessionFactory.openSession()) {
142-
SimpleTableAnnotatedMapper mapper = session.getMapper(SimpleTableAnnotatedMapper.class);
143-
144-
SelectStatementProvider selectStatement = select(id.as("A_ID"), firstName, lastName, birthDate, employed, occupation)
145-
.from(simpleTable)
146-
.where(id, isEqualTo(1))
147-
.or(occupation, isNull())
148-
.build()
149-
.render(RenderingStrategies.MYBATIS3);
150-
151-
List<SimpleTableRecord> rows = mapper.selectMany(selectStatement);
152-
153-
assertThat(rows.size()).isEqualTo(3);
154-
}
162+
@Test
163+
void testGeneralSelect() {
164+
try (SqlSession session = sqlSessionFactory.openSession()) {
165+
PersonMapper mapper = session.getMapper(PersonMapper.class);
166+
167+
SelectStatementProvider selectStatement = select(id.as("A_ID"), firstName, lastName, birthDate, employed,
168+
occupation, addressId)
169+
.from(person)
170+
.where(id, isEqualTo(1))
171+
.or(occupation, isNull())
172+
.build()
173+
.render(RenderingStrategies.MYBATIS3);
174+
175+
List<PersonRecord> rows = mapper.selectMany(selectStatement);
176+
assertThat(rows).hasSize(3);
155177
}
178+
}
179+
180+
@Test
181+
void testGeneralDelete() {
182+
try (SqlSession session = sqlSessionFactory.openSession()) {
183+
PersonMapper mapper = session.getMapper(PersonMapper.class);
184+
185+
DeleteStatementProvider deleteStatement = deleteFrom(person)
186+
.where(occupation, isNull())
187+
.build()
188+
.render(RenderingStrategies.MYBATIS3);
189+
190+
int rows = mapper.delete(deleteStatement);
191+
assertThat(rows).isEqualTo(2);
192+
}
193+
}
156194
```
195+
196+
If you use MyBatis Generator, the generator will create several additional utility methods in a mapper like this that
197+
will improve its usefulness. You can see a full example of the type of code created by MyBatis generator by looking
198+
at the full example at https://github.com/mybatis/mybatis-dynamic-sql/tree/master/src/test/java/examples/simple

src/site/markdown/docs/whereClauses.md

+24-14
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ Most of the conditions also support a subquery. For example:
6969
```
7070

7171
## Stand Alone Where Clauses
72-
You can use the where clause support on its own if you would rather code your own SQL for the remainder of a statement. There may be several reasons to do this - mainly if the library doesn't support some SQL or MyBatis feature you want to use. A good example would be paginated queries which are currently not support by the library. If you want to use a stand alone where clause, you can code a mapper method that looks like this:
72+
Although rare, you can use the where clause support on its own if you would rather code your own SQL for the remainder
73+
of a statement. There may be several reasons to do this - mainly if the library doesn't support some SQL or MyBatis
74+
feature you want to use. A good example would be if you want to append other SQL to the generated SQL produced by the
75+
library. If you want to use a stand alone where clause, you can code a mapper method that looks like this:
7376

7477
```java
7578
@Select({
@@ -78,7 +81,7 @@ You can use the where clause support on its own if you would rather code your ow
7881
"${whereClause}"
7982
})
8083
@ResultMap("AnimalDataResult")
81-
List<AnimalData> selectByExample(WhereClauseProvider whereClause);
84+
List<AnimalData> selectWithWhereClause(WhereClauseProvider whereClause);
8285
```
8386

8487
You can build a stand alone where clause and call your mapper like this:
@@ -88,12 +91,14 @@ You can build a stand alone where clause and call your mapper like this:
8891
.build()
8992
.render(RenderingStrategies.MYBATIS3);
9093

91-
List<AnimalData> animals = mapper.selectByExample(whereClause);
94+
List<AnimalData> animals = mapper.selectWithWhereClause(whereClause);
9295
```
93-
This method works well when there are no other parameters needed for the statement and when there are no table aliases involved. If you have those other needs, then see the following.
96+
This method works well when there are no other parameters needed for the statement and when there are no table aliases
97+
involved. If you have those other needs, then see the following.
9498

9599
### Table Aliases
96-
If you need to use a table alias in the generated where clause you can supply it on the render method using the `TableAliasCalculator` class. For example, if you have a mapper like this:
100+
If you need to use a table alias in the generated where clause you can supply it on the render method using the
101+
`TableAliasCalculator` class. For example, if you have a mapper like this:
97102

98103
```java
99104
@Select({
@@ -102,7 +107,7 @@ If you need to use a table alias in the generated where clause you can supply it
102107
"${whereClause}"
103108
})
104109
@ResultMap("AnimalDataResult")
105-
List<AnimalData> selectByExampleWithAlias(WhereClauseProvider whereClause);
110+
List<AnimalData> selectWithWhereClauseAndAlias(WhereClauseProvider whereClause);
106111
```
107112
Then you can specify the alias for the generated WHERE clause on the render method like this:
108113

@@ -111,12 +116,15 @@ Then you can specify the alias for the generated WHERE clause on the render meth
111116
.build()
112117
.render(RenderingStrategies.MYBATIS3, TableAliasCalculator.of(animalData, "a"));
113118

114-
List<AnimalData> animals = mapper.selectByExampleWithAlias(whereClause);
119+
List<AnimalData> animals = mapper.selectWithWhereClauseAndAlias(whereClause);
115120
```
116-
It is more likely that you will be using table aliases with hand coded joins where there is more than on table alias. In this case, you supply a `Map<SqlTable, String>` to the TableAliasCalculator that holds an alias for each table involved in the WHERE clause.
121+
It is more likely that you will be using table aliases with hand coded joins where there is more than on table alias.
122+
In this case, you supply a `Map<SqlTable, String>` to the TableAliasCalculator that holds an alias for each table
123+
involved in the WHERE clause.
117124

118125
### Handling Multiple Parameters
119-
By default, the WHERE clause renderer assumes that the rendered WHERE clause will be the only parameter to the mapper method. This is not always the case. For example, suppose you have a paginated query like this (this is HSQLDB syntax):
126+
By default, the WHERE clause renderer assumes that the rendered WHERE clause will be the only parameter to the mapper
127+
method. This is not always the case. For example, suppose you have a paginated query like this (this is HSQLDB syntax):
120128

121129
```java
122130
@Select({
@@ -127,19 +135,21 @@ By default, the WHERE clause renderer assumes that the rendered WHERE clause wil
127135
"OFFSET #{offset,jdbcType=INTEGER} LIMIT #{limit,jdbcType=INTEGER}"
128136
})
129137
@ResultMap("AnimalDataResult")
130-
List<AnimalData> selectByExampleWithLimitAndOffset(@Param("whereClauseProvider") WhereClauseProvider whereClause,
138+
List<AnimalData> selectWithWhereClauseLimitAndOffset(@Param("whereClauseProvider") WhereClauseProvider whereClause,
131139
@Param("limit") int limit, @Param("offset") int offset);
132140
```
133141

134-
In this mapper method there are three parameters. So in this case it will be necessary to tell the WHERE rendered what parameter name to use the for rendered where clause. That code looks like this:
142+
In this mapper method there are three parameters. So in this case it will be necessary to tell the WHERE rendered what
143+
parameter name to use the for rendered where clause. That code looks like this:
135144

136145
```java
137146
WhereClauseProvider whereClause = where(id, isLessThan(60))
138147
.build()
139148
.render(RenderingStrategies.MYBATIS3, "whereClauseProvider");
140149

141-
List<AnimalData> animals = mapper.selectByExampleWithLimitAndOffset(whereClause, 5, 15);
150+
List<AnimalData> animals = mapper.selectWithWhereClauseLimitAndOffset(whereClause, 5, 15);
142151
```
143-
Notice that the string `whereClauseProvider` is used both as the parameter name in the mapper `@Param` annotation and the parameter name in the `render` method.
152+
Notice that the string `whereClauseProvider` is used both as the parameter name in the mapper `@Param` annotation,
153+
and the parameter name in the `render` method.
144154

145-
The render method also has an override that accepts a TableAliasCalculator and a parameter name.
155+
The render method also has an override that accepts a `TableAliasCalculator` and a parameter name.

0 commit comments

Comments
 (0)