Skip to content

Commit

Permalink
Merge pull request #358 from jeffgbutler/final-doc-updates
Browse files Browse the repository at this point in the history
Doc Updates for Release
  • Loading branch information
jeffgbutler authored May 6, 2021
2 parents bb0d1e4 + a06d306 commit 4eeb56f
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 79 deletions.
44 changes: 34 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This log will detail notable changes to MyBatis Dynamic SQL. Full details are available on the GitHub milestone pages.

## Release 1.3.0 - Unreleased
## Release 1.3.0 - May 6, 2021

GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.3.0+](https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.3.0+)

Expand All @@ -13,13 +13,14 @@ The major themes of this release include the following:
1. Add support for subqueries in select statements - both in a from clause and a join clause.
1. Add support for the "exists" and "not exists" operator. This will work in "where" clauses anywhere
they are supported.
1. Refactor and improve the built-in conditions for consistency (see below)
1. Continue to refine the Kotlin DSL. Most changes to the Kotlin DSL are internal and should be source code
1. Refactor and improve the built-in conditions for consistency (see below). There is one breaking change also
detailed below.
1. Continue to refine the Kotlin DSL. Many changes to the Kotlin DSL are internal and should be source code
compatible with existing code. There is one breaking change detailed below.
1. Remove deprecated code from prior releases.

### Built-In Condition Refactoring
All built-in conditions have been refactored. The changes should have no impact for the vast majority of users.
### Built-In Condition Refactoring and Breaking Change
All built-in conditions have been refactored. The changes should have little impact for the vast majority of users.
However, there are some changes in behavior and one breaking change.

1. Internally, the conditions no longer hold value Suppliers, they now hold the values themselves. The SqlBuilder
Expand All @@ -31,13 +32,14 @@ However, there are some changes in behavior and one breaking change.
for a similar purpose.
1. The new "filter" method works a bit differently than the "when" method it replaces. The old "when" method could not
be chained - if it was called multiple times, only the last call would take effect. The new "filter" methods works
as it should and every call will take effect.
as it should and every call will take effect. This allows you to construct map/filter pipelines as you would
expect.
1. The new "map" method will allow you to change the datatype of a condition as is normal for a "map" method. You
can use this method to apply a type conversion directly within condition.
1. All the "WhenPresent" conditions have been removed as separate classes. The methods that produced these conditions
in the SqlBuilder remain, and they will now produce a condition with a "NotNull" filter applied. So at the API level
things will function exactly as before, but the intermediate classes will be different.
1. One breaking change is that the builder for List value conditions has been removed without replacement. If you
1. One **breaking change** is that the builder for List value conditions has been removed without replacement. If you
were using this builder to supply a "value stream transformer", then the replacement is to build a new List value
condition and then call the "map" and "filter" methods as needed. For example, prior code looked like this

Expand All @@ -62,9 +64,31 @@ However, there are some changes in behavior and one breaking change.
```
We think this is a marked improvement!

### Breaking Change for Kotlin
### Kotlin DSL Update and Breaking Change for Kotlin

In this release the Kotlin support for `select` and `count` statements has been refactored. This will not impact code
The Kotlin DSL continues to evolve. With this release we have fully built out the DSL, and it is no longer necessary
to use any functions in `org.mybatis.dynamic.sql.SqlBuilder`. The advantages of this are many and are detailed on the
Kotlin overview page in the documentation. Many functions in `SqlBuilder` have been replaced by
top level functions the `org.mybatis.dynamic.sql.util.kotlin.elements` package. In most cases you can switch to the
native Kotlin DSL by simply changing the import statements. For example, you can switch usage of the `isEqualTo`
function by changing

```kotlin
import org.mybatis.dynamic.sql.SqlBuilder.isEqualTo
```

to

```kotlin
import org.mybatis.dynamic.sql.util.kotlin.elements.isEqualTo
```

Several functions that accepted supplier arguments are not present in the Kotlin DSL. This is to avoid difficult
and confusing method overload problems for methods that did not offer any real benefit. If you were using one of these
methods in the Java DSL, then in the Kotlin DSL you will have to change the function argument from a supplier to the
actual value itself.

A **breaking change** is that Kotlin support for `select` and `count` statements has been refactored. This will not impact code
created by MyBatis generator. It will have an impact on Spring/Kotlin users as well as MyBatis users that coded joins or
other queries directly in Kotlin. The difference is that the `from` clause has been moved inside the lambda for select
and count statements.
Expand All @@ -84,7 +108,7 @@ The new code looks like this:
}
```

This change makes the Kotlin DSL a bit more consistent and also makes it easier to implement subquery support in the
This change makes the Kotlin DSL more consistent and also makes it easier to implement subquery support in the
Kotlin DSL.

### Added
Expand Down
4 changes: 2 additions & 2 deletions checkstyle-override.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
Copyright 2016-2020 the original author or authors.
Copyright 2016-2021 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -217,7 +217,7 @@
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="accessModifiers" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
Expand Down
1 change: 0 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
<clirr.comparisonVersion>1.2.0</clirr.comparisonVersion>
<module.name>org.mybatis.dynamic.sql</module.name>
<kotlin.version>1.5.0</kotlin.version>
<jacoco.version>0.8.7</jacoco.version>
<kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
<sonar.sources>pom.xml,src/main/java,src/main/kotlin</sonar.sources>
<sonar.tests>src/test/java,src/test/kotlin</sonar.tests>
Expand Down
42 changes: 29 additions & 13 deletions src/site/markdown/docs/complexQueries.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Complex Queries
Enhancements in version 1.1.2 make it easier to code complex queries. The Select DSL is implemented as a set of related objects. As the select statement is built, intermediate objects of various types are returned from the various methods that implement the DSL. The select statement can be completed by calling the `build()` method many of the intermediate objects. Prior to version 1.1.2, it was necessary to call `build()` on the **last** intermediate object. This restriction has been removed, and it is now possible to call `build()` on **any** intermediate object. This, along with several other enhancements, has simplified the coding of complex queries.
Enhancements in version 1.1.2 make it easier to code complex queries. The Select DSL is implemented as a set of related
objects. As the select statement is built, intermediate objects of various types are returned from the various methods
that implement the DSL. The select statement can be completed by calling the `build()` method many of the intermediate
objects. Prior to version 1.1.2, it was necessary to call `build()` on the **last** intermediate object. This
restriction has been removed, and it is now possible to call `build()` on **any** intermediate object. This, along with
several other enhancements, has simplified the coding of complex queries.

For example, suppose you want to code a complex search on a Person table. The search parameters are id, first name, and last name. The rules are:
For example, suppose you want to code a complex search on a Person table. The search parameters are id, first name,
and last name. The rules are:

1. If an id is entered, use the id and ignore the other search parameters
1. If an id is not entered, then do a fuzzy search based on the other parameters
Expand All @@ -19,15 +25,15 @@ public SelectStatementProvider search(Integer targetId, String fName, String lNa
.and(id, isEqualTo(targetId));
} else {
builder
.and(firstName, isLike(fName).when(Objects::nonNull).then(s -> "%" + s + "%")) // (4)
.and(lastName, isLikeWhenPresent(lName).then(this::addWildcards)); // (5)
.and(firstName, isLike(fName).filter(Objects::nonNull).map(s -> "%" + s + "%")) // (4) (5)
.and(lastName, isLikeWhenPresent(lName).map(this::addWildcards)); // (6)
}

builder
.orderBy(lastName, firstName)
.fetchFirst(50).rowsOnly(); // (6)
.fetchFirst(50).rowsOnly(); // (7)

return builder.build().render(RenderingStrategies.MYBATIS3); // (7)
return builder.build().render(RenderingStrategies.MYBATIS3); // (8)
}

public String addWildcards(String s) {
Expand All @@ -37,11 +43,21 @@ public String addWildcards(String s) {

Notes:

1. Note the use of the `var` keyword here. If you are using an older version of Java, the actual type is `QueryExpressionDSL<SelectModel>.QueryExpressionWhereBuilder`
1. Here we are calling `where()` with no parameters. This sets up the builder to accept conditions further along in the code. If no conditions are added, then the where clause will not be rendered
1. This `if` statement implements the rules of the search. If an ID is entered , use it. Otherwise, do a fuzzy search based on first name and last name.
1. The `then` statement on this line allows you to change the parameter value before it is placed in the parameter Map. In this case we are adding SQL wildcards to the start and end of the search String - but only if the search String is not null. If the search String is null, the lambda will not be called and the condition will not render
1. This shows using a method reference instead of a lambda on the `then`. Method references allow you to more clearly express intent. Note also the use of the `isLikeWhenPresent` condition which is a built in condition that checks for nulls
1. It is a good idea to limit the number of rows returned from a search. The library now supports `fetch first` syntax for limiting rows
1. Note that we are calling the `build` method from the intermediate object retrieved in step 1. It is no longer necessary to call `build` on the last object returned from a select builder
1. Note the use of the `var` keyword here. If you are using an older version of Java, the actual type is
`QueryExpressionDSL<SelectModel>.QueryExpressionWhereBuilder`
1. Here we are calling `where()` with no parameters. This sets up the builder to accept conditions further along in the
code. If no conditions are added, then the where clause will not be rendered
1. This `if` statement implements the rules of the search. If an ID is entered , use it. Otherwise, do a fuzzy search
based on first name and last name.
1. The `filter` method on this line will mark the condition as unrenderable if the filter is not satisfied.
1. The `map` statement on this line allows you to change the parameter value before it is placed in the parameter Map.
In this case we are adding SQL wildcards to the start and end of the search String - but only if the search String
is not null. If the search String is null, the lambda will not be called and the condition will not render
1. This line shows the use of a method reference instead of a lambda on the `map`. Method references allow you to more
clearly express intent. Note also the use of the `isLikeWhenPresent` function which is a built-in function that
applies a non-null filter
1. It is a good idea to limit the number of rows returned from a search. The library now supports `fetch first` syntax
for limiting rows
1. Note that we are calling the `build` method from the intermediate object retrieved in step 1. It is no longer
necessary to call `build` on the last object returned from a select builder

Loading

0 comments on commit 4eeb56f

Please sign in to comment.