Skip to content

Commit 4984924

Browse files
committed
Docs
1 parent f888b83 commit 4984924

File tree

5 files changed

+168
-83
lines changed

5 files changed

+168
-83
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ Other important changes:
3131
With this change, the exception thrown is more predictable and the error is caught before sending the SQL to the
3232
database.
3333
- All the paging methods (limit, offset, fetchFirst) now have "WhenPresent" variations that will drop the phrase from
34-
rendering if a null value is passed in
34+
rendering if a null value is passed in
35+
- The JOIN syntax is updated and now allows full boolean expressions like a WHERE clause. The prior JOIN syntax
36+
is deprecated and will be removed in a future release.
3537

3638
## Release 1.5.2 - June 3, 2024
3739

src/site/markdown/docs/kotlinOverview.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,9 @@ val selectStatement = select(orderMaster.orderId, orderMaster.orderDate, orderDe
417417
orderDetail.description, orderDetail.quantity
418418
) {
419419
from(orderMaster, "om")
420-
join(orderDetail, "od") {
421-
on(orderMaster.orderId) equalTo orderDetail.orderId
422-
and(orderMaster.orderId) equalTo orderDetail.orderId
420+
join(orderDetail, "od") on {
421+
orderMaster.orderId isEqualTo orderDetail.orderId
422+
and { orderMaster.orderId isEqualTo orderDetail.orderId }
423423
}
424424
where { orderMaster.orderId isEqualTo 1 }
425425
or {
@@ -433,8 +433,7 @@ val selectStatement = select(orderMaster.orderId, orderMaster.orderDate, orderDe
433433

434434
In a select statement you must specify a table in a `from` clause. Everything else is optional.
435435

436-
Multiple join clauses can be specified if you need to join additional tables. In a join clause, you must
437-
specify an `on` condition, and you may specify additional `and` conditions as necessary. Full, left, right, inner,
436+
Multiple join clauses can be specified if you need to join additional tables. Full, left, right, inner,
438437
and outer joins are supported.
439438

440439
Where clauses can be of arbitrary complexity and support all SQL operators including exists operators, subqueries, etc.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# V1 to V2 Migration Guide
2+
3+
Version 2 of MyBatis Dynamic SQL introduced many new features. This page will document how to migrate code
4+
from prior releases to version 2.
5+
6+
## Java Join Syntax
7+
8+
Version2 offers a fully flexible join specification and reuses the capabilities of where clauses. Of course,
9+
not all capabilities are supported in databases, but you should now be able to code any type of join specification.
10+
11+
The changes in the Java DSL are mostly internal and should not impact most users. The `equalTo` methods has been
12+
deprecated in favor of `isEqualTo`, but all other changes should be hidden.
13+
14+
V1 Join Specification Example:
15+
```java
16+
SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDetail.lineNumber, orderDetail.quantity)
17+
.from(orderMaster, "om")
18+
.join(orderDetail, "od", on(orderMaster.orderId, equalTo(orderDetail.orderId)))
19+
.build()
20+
.render(RenderingStrategies.MYBATIS3);
21+
```
22+
23+
V2 Join Specification Example:
24+
```java
25+
SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDetail.lineNumber, orderDetail.quantity)
26+
.from(orderMaster, "om")
27+
.join(orderDetail, "od", on(orderMaster.orderId, isEqualTo(orderDetail.orderId)))
28+
.build()
29+
.render(RenderingStrategies.MYBATIS3);
30+
```
31+
32+
## Kotlin Join Syntax
33+
34+
Like the Java DSL, the V2 Kotlin DSL offers a fully flexible join specification and reuses the capabilities of where
35+
clauses. Of course, not all capabilities are supported in databases, but you should now be able to code any type of
36+
join specification.
37+
38+
The changes in the Kotlin DSL allow a more natural expressions of a join specification. The main difference is that
39+
the "on" keyword should be moved outside the join specification lambda (it is now an infix function). Inside the lambda,
40+
the conditions should be rewritten to match the syntax of a where clause.
41+
42+
V1 Join Specification Example:
43+
```kotlin
44+
val selectStatement = select(
45+
orderMaster.orderId, orderMaster.orderDate,
46+
orderDetail.lineNumber, orderDetail.description, orderDetail.quantity
47+
) {
48+
from(orderMaster, "om")
49+
join(orderDetail, "od") {
50+
on(orderMaster.orderId) equalTo orderDetail.orderId
51+
and(orderMaster.orderId) equalTo constant("1")
52+
}
53+
}
54+
```
55+
56+
V2 Join Specification Example:
57+
```kotlin
58+
val selectStatement = select(
59+
orderMaster.orderId, orderMaster.orderDate,
60+
orderDetail.lineNumber, orderDetail.description, orderDetail.quantity
61+
) {
62+
from(orderMaster, "om")
63+
join(orderDetail, "od") on {
64+
orderMaster.orderId isEqualTo orderDetail.orderId
65+
and { orderMaster.orderId isEqualTo constant("1") }
66+
}
67+
}
68+
69+
```

src/site/markdown/docs/select.md

Lines changed: 91 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ In general, the following are supported:
1010
2. Tables can be aliased per select statement
1111
3. Columns can be aliased per select statement
1212
4. Some support for aggregates (avg, min, max, sum)
13-
5. Equijoins of type INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER
13+
5. Joins of type INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER
1414
6. Subqueries in where clauses. For example, `where foo in (select foo from foos where id < 36)`
1515
7. Select from another select. For example `select count(*) from (select foo from foos where id < 36)`
1616
8. Multi-Selects. For example `(select * from foo order by id limit 3) union (select * from foo order by id desc limit 3)`
@@ -21,47 +21,50 @@ At this time, the library does not support the following:
2121
2. INTERSECT, EXCEPT, etc.
2222

2323
The user guide page for WHERE Clauses shows examples of many types of SELECT statements with different complexities of
24-
the WHERE clause including support for sub-queries. We will just show a single example here, including an ORDER BY clause:
24+
the WHERE clause including support for sub-queries. We will just show a single example here, including an ORDER BY
25+
clause:
2526

2627
```java
27-
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
28-
.from(animalData)
29-
.where(id, isIn(1, 5, 7))
30-
.and(bodyWeight, isBetween(1.0).and(3.0))
31-
.orderBy(id.descending(), bodyWeight)
32-
.build()
33-
.render(RenderingStrategies.MYBATIS3);
34-
35-
List<AnimalData> animals = mapper.selectMany(selectStatement);
28+
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
29+
.from(animalData)
30+
.where(id, isIn(1, 5, 7))
31+
.and(bodyWeight, isBetween(1.0).and(3.0))
32+
.orderBy(id.descending(), bodyWeight)
33+
.build()
34+
.render(RenderingStrategies.MYBATIS3);
35+
36+
List<AnimalData> animals = mapper.selectMany(selectStatement);
3637
```
3738

3839
The WHERE and ORDER BY clauses are optional.
3940

4041
## Joins
41-
The library supports the generation of equijoin statements - joins defined by column matching. For example:
42+
The library supports the generation of join statements. For example:
4243

4344
```java
44-
SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderDetail.lineNumber, orderDetail.description, orderDetail.quantity)
45-
.from(orderMaster, "om")
46-
.join(orderDetail, "od").on(orderMaster.orderId, equalTo(orderDetail.orderId))
47-
.build()
48-
.render(RenderingStrategies.MYBATIS3);
45+
SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderDetail.lineNumber, orderDetail.description, orderDetail.quantity)
46+
.from(orderMaster, "om")
47+
.join(orderDetail, "od").on(orderMaster.orderId, isEqualTo(orderDetail.orderId))
48+
.build()
49+
.render(RenderingStrategies.MYBATIS3);
4950
```
5051

51-
Notice that you can give an alias to a table if desired. If you don't specify an alias, the full table name will be used in the generated SQL.
52+
Notice that you can give an alias to a table if desired. If you don't specify an alias, the full table name will be
53+
used in the generated SQL.
5254

5355
Multiple tables can be joined in a single statement. For example:
5456

5557
```java
56-
SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderLine.lineNumber, itemMaster.description, orderLine.quantity)
57-
.from(orderMaster, "om")
58-
.join(orderLine, "ol").on(orderMaster.orderId, equalTo(orderLine.orderId))
59-
.join(itemMaster, "im").on(orderLine.itemId, equalTo(itemMaster.itemId))
60-
.where(orderMaster.orderId, isEqualTo(2))
61-
.build()
62-
.render(RenderingStrategies.MYBATIS3);
58+
SelectStatementProvider selectStatement = select(orderMaster.orderId, orderDate, orderLine.lineNumber, itemMaster.description, orderLine.quantity)
59+
.from(orderMaster, "om")
60+
.join(orderLine, "ol").on(orderMaster.orderId, isEqualTo(orderLine.orderId))
61+
.join(itemMaster, "im").on(orderLine.itemId, isEqualTo(itemMaster.itemId))
62+
.where(orderMaster.orderId, isEqualTo(2))
63+
.build()
64+
.render(RenderingStrategies.MYBATIS3);
6365
```
64-
Join queries will likely require you to define a MyBatis result mapping in XML. This is the only instance where XML is required. This is due to the limitations of the MyBatis annotations when mapping collections.
66+
Join queries will likely require you to define a MyBatis result mapping in XML. This is the only instance where XML is
67+
required. This is due to the limitations of the MyBatis annotations when mapping collections.
6568

6669
The library supports four join types:
6770

@@ -74,14 +77,14 @@ The library supports four join types:
7477
The library supports the generation of UNION and UNION ALL queries. For example:
7578

7679
```java
77-
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
78-
.from(animalData)
79-
.union()
80-
.selectDistinct(id, animalName, bodyWeight, brainWeight)
81-
.from(animalData)
82-
.orderBy(id)
83-
.build()
84-
.render(RenderingStrategies.MYBATIS3);
80+
SelectStatementProvider selectStatement = select(id, animalName, bodyWeight, brainWeight)
81+
.from(animalData)
82+
.union()
83+
.selectDistinct(id, animalName, bodyWeight, brainWeight)
84+
.from(animalData)
85+
.orderBy(id)
86+
.build()
87+
.render(RenderingStrategies.MYBATIS3);
8588
```
8689

8790
Any number of SELECT statements can be added to a UNION query. Only one ORDER BY phrase is allowed.
@@ -96,16 +99,16 @@ Multi-select queries are a special case of union select statements. The differen
9699
paging clauses can be applied to the merged queries. For example:
97100

98101
```java
99-
SelectStatementProvider selectStatement = multiSelect(
100-
select(id, animalName, bodyWeight, brainWeight)
101-
.from(animalData)
102-
.orderBy(id)
103-
.limit(2)
102+
SelectStatementProvider selectStatement = multiSelect(
103+
select(id, animalName, bodyWeight, brainWeight)
104+
.from(animalData)
105+
.orderBy(id)
106+
.limit(2)
104107
).union(
105-
selectDistinct(id, animalName, bodyWeight, brainWeight)
106-
.from(animalData)
107-
.orderBy(id.descending())
108-
.limit(3)
108+
selectDistinct(id, animalName, bodyWeight, brainWeight)
109+
.from(animalData)
110+
.orderBy(id.descending())
111+
.limit(3)
109112
)
110113
.build()
111114
.render(RenderingStrategies.MYBATIS3);
@@ -114,7 +117,8 @@ paging clauses can be applied to the merged queries. For example:
114117
## MyBatis Mapper for Select Statements
115118

116119
The SelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you
117-
are using an annotated mapper, the select method should look like this (note that we recommend coding a "selectMany" and a "selectOne" method with a shared result mapping):
120+
are using an annotated mapper, the select method should look like this (note that we recommend coding a "selectMany"
121+
and a "selectOne" method with a shared result mapping):
118122

119123
```java
120124
import org.apache.ibatis.annotations.Result;
@@ -143,7 +147,9 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
143147

144148
## XML Mapper for Join Statements
145149

146-
If you are coding a join, it is likely you will need to code an XML mapper to define the result map. This is due to a MyBatis limitation - the annotations cannot define a collection mapping. If you have to do this, the Java code looks like this:
150+
If you are coding a join, it is likely you will need to code an XML mapper to define the result map. This is due to a
151+
MyBatis limitation - the annotations cannot define a collection mapping. If you have to do this, the Java code looks
152+
like this:
147153

148154
```java
149155
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@@ -171,7 +177,8 @@ And the corresponding XML looks like this:
171177
Notice that the resultMap is the only element in the XML mapper. This is our recommended practice.
172178

173179
## XML Mapper for Select Statements
174-
We do not recommend using an XML mapper for select statements, but if you want to do so the SelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly.
180+
We do not recommend using an XML mapper for select statements, but if you want to do so the SelectStatementProvider
181+
object can be used as a parameter to a MyBatis mapper method directly.
175182

176183
If you are using an XML mapper, the select method should look like this in the Java interface:
177184

@@ -205,30 +212,33 @@ Order by phrases can be difficult to calculate when there are aliased columns, a
205212
This library has taken a relatively simple approach:
206213

207214
1. When specifying an SqlColumn in an ORDER BY phrase the library will either write the column alias or the column
208-
name into the ORDER BY phrase. For the ORDER BY phrase, the table alias (if there is one) will be ignored. Use this pattern
209-
when the ORDER BY column is a member of the select list. For example `orderBy(foo)`. If the column has an alias, then
210-
it is easist to use the "arbitrary string" method with the column alias as shown below.
211-
1. It is also possible to explicitly specify a table alias for a column in an ORDER BY phrase. Use this pattern when
212-
there is a join, and the ORDER BY column is in two or more tables, and the ORDER BY column is not in the select
213-
list. For example `orderBy(sortColumn("t1", foo))`.
214-
1. If none of the above use cases meet your needs, then you can specify an arbitrary String to write into the rendered ORDER BY
215-
phrase (see below for an example).
215+
name into the ORDER BY phrase. For the ORDER BY phrase, the table alias (if there is one) will be ignored. Use this
216+
pattern when the ORDER BY column is a member of the select list. For example `orderBy(foo)`. If the column has an
217+
alias, then it is easiest to use the "arbitrary string" method with the column alias as shown below.
218+
2. It is also possible to explicitly specify a table alias for a column in an ORDER BY phrase. Use this pattern when
219+
there is a join, and the ORDER BY column is in two or more tables, and the ORDER BY column is not in the select
220+
list. For example `orderBy(sortColumn("t1", foo))`.
221+
3. If none of the above use cases meet your needs, then you can specify an arbitrary String to write into the rendered
222+
ORDER BY phrase (see below for an example).
216223

217224
In our testing, this caused an issue in only one case. When there is an outer join and the select list contains
218225
both the left and right join column. In that case, the workaround is to supply a column alias for both columns.
219226

220-
When using a column function (lower, upper, etc.), then it is customary to give the calculated column an alias so you will have a predictable result set. In cases like this there will not be a column to use for an alias. The library supports arbitrary values in an ORDER BY expression like this:
227+
When using a column function (lower, upper, etc.), then it is customary to give the calculated column an alias so you
228+
will have a predictable result set. In cases like this there will not be a column to use for an alias. The library
229+
supports arbitrary values in an ORDER BY expression like this:
221230

222231
```java
223-
SelectStatementProvider selectStatement = select(substring(gender, 1, 1).as("ShortGender"), avg(age).as("AverageAge"))
224-
.from(person, "a")
225-
.groupBy(substring(gender, 1, 1))
226-
.orderBy(sortColumn("ShortGender").descending())
227-
.build()
228-
.render(RenderingStrategies.MYBATIS3);
232+
SelectStatementProvider selectStatement = select(substring(gender, 1, 1).as("ShortGender"), avg(age).as("AverageAge"))
233+
.from(person, "a")
234+
.groupBy(substring(gender, 1, 1))
235+
.orderBy(sortColumn("ShortGender").descending())
236+
.build()
237+
.render(RenderingStrategies.MYBATIS3);
229238
```
230239

231-
In this example the `substring` function is used in both the select list and the GROUP BY expression. In the ORDER BY expression, we use the `sortColumn` function to duplicate the alias given to the column in the select list.
240+
In this example the `substring` function is used in both the select list and the GROUP BY expression. In the ORDER BY
241+
expression, we use the `sortColumn` function to duplicate the alias given to the column in the select list.
232242

233243
## Limit and Offset Support
234244
Since version 1.1.1 the select statement supports limit and offset for paging (or slicing) queries. You can specify:
@@ -237,18 +247,22 @@ Since version 1.1.1 the select statement supports limit and offset for paging (o
237247
- Offset only
238248
- Both limit and offset
239249

240-
It is important to note that the select renderer writes limit and offset clauses into the generated select statement as is. The library does not attempt to normalize those values for databases that don't support limit and offset directly. Therefore, it is very important for users to understand whether or not the target database supports limit and offset. If the target database does not support limit and offset, then it is likely that using this support will create SQL that has runtime errors.
250+
It is important to note that the select renderer writes limit and offset clauses into the generated select statement as
251+
is. The library does not attempt to normalize those values for databases that don't support limit and offset directly.
252+
Therefore, it is very important for users to understand whether the target database supports limit and offset.
253+
If the target database does not support limit and offset, then it is likely that using this support will create SQL
254+
that has runtime errors.
241255

242256
An example follows:
243257

244258
```java
245-
SelectStatementProvider selectStatement = select(animalData.allColumns())
246-
.from(animalData)
247-
.orderBy(id)
248-
.limit(3)
249-
.offset(22)
250-
.build()
251-
.render(RenderingStrategies.MYBATIS3);
259+
SelectStatementProvider selectStatement = select(animalData.allColumns())
260+
.from(animalData)
261+
.orderBy(id)
262+
.limit(3)
263+
.offset(22)
264+
.build()
265+
.render(RenderingStrategies.MYBATIS3);
252266
```
253267

254268
## Fetch First Support
@@ -263,11 +277,11 @@ Fetch first is an SQL standard and is supported by most databases.
263277
An example follows:
264278

265279
```java
266-
SelectStatementProvider selectStatement = select(animalData.allColumns())
267-
.from(animalData)
268-
.orderBy(id)
269-
.offset(22)
270-
.fetchFirst(3).rowsOnly()
271-
.build()
272-
.render(RenderingStrategies.MYBATIS3);
280+
SelectStatementProvider selectStatement = select(animalData.allColumns())
281+
.from(animalData)
282+
.orderBy(id)
283+
.offset(22)
284+
.fetchFirst(3).rowsOnly()
285+
.build()
286+
.render(RenderingStrategies.MYBATIS3);
273287
```

src/site/site.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<menu name="User's Guide">
3737
<item href="docs/introduction.html" name="Introduction" />
3838
<item href="docs/CHANGELOG.html" name="Change Log" />
39+
<item href="docs/migratingV1toV2.html" name="Migrating from V1 to V2" />
3940
<item href="docs/quickStart.html" name="Quick Start" />
4041
<item href="docs/exceptions.html" name="Exceptions thrown by the Library" />
4142
<item href="docs/configuration.html" name="Configuration of the Library" />

0 commit comments

Comments
 (0)