Skip to content

Commit a79770d

Browse files
authored
Merge pull request #767 from jeffgbutler/simplification
General Refactoring
2 parents d61d7c0 + d86f687 commit a79770d

34 files changed

+142
-132
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This log will detail notable changes to MyBatis Dynamic SQL. Full details are av
66

77
This is a minor release with several enhancements.
88

9-
GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/milestone/13](https://github.com/mybatis/mybatis-dynamic-sql/milestone/13)
9+
GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/milestone/13?closed=1](https://github.com/mybatis/mybatis-dynamic-sql/milestone/13?closed=1)
1010

1111
### Case Expressions and Cast Function
1212
We've added support for CASE expressions to the library. Both simple and searched case expressions are supported.

README.md

+46-36
Original file line numberDiff line numberDiff line change
@@ -9,63 +9,73 @@
99
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=mybatis_mybatis-dynamic-sql&metric=security_rating)](https://sonarcloud.io/dashboard?id=mybatis_mybatis-dynamic-sql)
1010

1111
## What Is This?
12-
This library is a general purpose SQL generator. Think of it as a typesafe and expressive SQL DSL (domain specific language),
13-
with support for rendering SQL formatted properly for MyBatis3 and Spring's NamedParameterJDBCTemplate.
12+
This library is a general purpose SQL generator. Think of it as a typesafe and expressive SQL DSL (domain specific
13+
language), with support for rendering SQL formatted properly for MyBatis3 and Spring's NamedParameterJDBCTemplate.
1414

1515
The library also contains extensions for Kotlin that enable an idiomatic Kotlin DSL for SQL.
1616

1717
The library will generate full DELETE, INSERT, SELECT, and UPDATE statements. The DSL implemented by the
18-
library is very similar to native SQL but it includes many functions that allow for very dynamic SQL statements.
19-
For example, a typical search can be coded with a query like this (the following code is Kotlin, but Java code is very similar):
18+
library is very similar to native SQL, but it includes many functions that allow for very dynamic SQL statements.
19+
For example, a typical search can be coded with a query like this (the following code is Kotlin, but Java code is very
20+
similar):
2021

2122
```kotlin
22-
fun search(id: String?, firstName: String?, lastName: String?) =
23-
select(Customer.id, Customer.firstName, Customer.lastName) {
23+
data class SearchParameters(val id: String?, val firstName: String?, val lastName: String?)
24+
25+
fun search(searchParameters: SearchParameters) =
26+
select(id, firstName, lastName) {
2427
from(Customer)
25-
where { Customer.active.isTrue() }
26-
and { Customer.id (isEqualToWhenPresent(id).map{ it?.padStart(5, '0') }) }
27-
and { Customer.firstName (isLikeCaseInsensitiveWhenPresent(firstName)
28-
.map{ "%" + it.trim() + "%" }) }
29-
and { Customer.lastName (isLikeCaseInsensitiveWhenPresent(lastName)
30-
.map{ "%" + it.trim() + "%" }) }
31-
orderBy(Customer.lastName, Customer.firstName)
28+
where {
29+
active isEqualTo true
30+
and { id isEqualToWhenPresent searchParameters.id }
31+
and {
32+
firstName(isLikeCaseInsensitiveWhenPresent(searchParameters.firstName)
33+
.map { "%" + it.trim() + "%" })
34+
}
35+
and {
36+
lastName(isLikeCaseInsensitiveWhenPresent(searchParameters.lastName)
37+
.map { "%" + it.trim() + "%" })
38+
}
39+
}
40+
orderBy(lastName, firstName)
3241
limit(500)
3342
}
3443
```
3544

3645
This query does quite a lot...
3746

3847
1. It is a search with three search criteria - any combination of search criteria can be used
39-
1. Only records with an active status will be returned
40-
1. If `id` is specified, it will be padded to length 5 with '0' at the beginning of the string
41-
1. If `firstName` is specified, it will be used in a case-insensitive search and SQL wildcards will be appended
42-
1. If `lastName` is specified, it will be used in a case-insensitive search and SQL wildcards will be appended
43-
1. The query results are limited to 500 rows
48+
2. Only records with an active status will be returned
49+
3. If `id` is specified, it will be used as a filter
50+
4. If `firstName` is specified, it will be used in a case-insensitive search and SQL wildcards will be appended
51+
5. If `lastName` is specified, it will be used in a case-insensitive search and SQL wildcards will be appended
52+
6. The query results are limited to 500 rows
4453

45-
Using the dynamic SQL features of the library eliminates a lot of code that would be required for checking nulls, adding wild cards, etc. This query clearly expresses the intent of the search in just a few lines.
54+
Using the dynamic SQL features of the library eliminates a lot of code that would be required for checking nulls,
55+
adding wild cards, etc. This query clearly expresses the intent of the search in just a few lines.
4656

4757
See the following pages for detailed information:
4858

49-
| Page | Comments|
50-
|------|---------|
51-
|[Quick Start](src/site/markdown/docs/quickStart.md) | Shows a complete example of building code for this library |
52-
|[MyBatis3 Support](src/site/markdown/docs/mybatis3.md) | Information about specialized support for [MyBatis3](https://github.com/mybatis/mybatis-3). The examples on this page are similar to the code generated by [MyBatis Generator](https://github.com/mybatis/generator) |
53-
|[Kotlin Support with MyBatis3](src/site/markdown/docs/kotlinMyBatis3.md) | Information about the Kotlin extensions and Kotlin DSL when using MyBatis3 as the runtime |
54-
|[Spring Support](src/site/markdown/docs/spring.md) | Information about specialized support for Spring JDBC Templates |
55-
|[Kotlin Support with Spring](src/site/markdown/docs/kotlinSpring.md) | Information about the Kotlin extensions and Kotlin DSL when using Spring JDBC Template as the runtime |
56-
|[Spring Batch Support](src/site/markdown/docs/springBatch.md) | Information about specialized support for Spring Batch using the [MyBatis Spring Integration](https://github.com/mybatis/spring) |
59+
| Page | Comments |
60+
|--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
61+
| [Quick Start](src/site/markdown/docs/quickStart.md) | Shows a complete example of building code for this library |
62+
| [MyBatis3 Support](src/site/markdown/docs/mybatis3.md) | Information about specialized support for [MyBatis3](https://github.com/mybatis/mybatis-3). The examples on this page are similar to the code generated by [MyBatis Generator](https://github.com/mybatis/generator) |
63+
| [Kotlin Support with MyBatis3](src/site/markdown/docs/kotlinMyBatis3.md) | Information about the Kotlin extensions and Kotlin DSL when using MyBatis3 as the runtime |
64+
| [Spring Support](src/site/markdown/docs/spring.md) | Information about specialized support for Spring JDBC Templates |
65+
| [Kotlin Support with Spring](src/site/markdown/docs/kotlinSpring.md) | Information about the Kotlin extensions and Kotlin DSL when using Spring JDBC Template as the runtime |
66+
| [Spring Batch Support](src/site/markdown/docs/springBatch.md) | Information about specialized support for Spring Batch using the [MyBatis Spring Integration](https://github.com/mybatis/spring) |
5767

5868
The library test cases provide several complete examples of using the library in various different styles:
5969

60-
| Language | Runtime | Comments | Code Directory |
61-
|---|---|---|---|
62-
| Java | MyBatis3 | Example using Java utility classes for MyBatis in the style of MyBatis Generator | [../examples/simple](src/test/java/examples/simple) |
63-
| Java | MyBatis3 + MyBatis-Spring | Example using MyBatis-Spring integration | [../examples/column/comparison](src/test/java/examples/column/comparison) |
64-
| Java | MyBatis3 + MyBatis-Spring (Spring Batch)| Example using Java utility classes for the MyBatis integration with Spring Batch | [../examples/springbatch](src/test/java/examples/springbatch) |
65-
| Java | Spring JDBC | Example using Java utility classes for Spring JDBC Template | [../examples/spring](src/test/java/examples/spring) |
66-
| Kotlin | MyBatis3 | Example using Kotlin utility classes for MyBatis in the style of MyBatis Generator | [../examples/kotlin/mybatis3/canonical](src/test/kotlin/examples/kotlin/mybatis3/canonical) |
67-
| Kotlin | MyBatis3 + MyBatis-Spring | Example using MyBatis-Spring integration in Kotlin | [../examples/kotlin/mybatis3/column/comparison](src/test/kotlin/examples/kotlin/mybatis3/column/comparison) |
68-
| Kotlin | Spring JDBC | Example using Kotlin utility classes for Spring JDBC Template | [../examples/kotlin/spring/canonical](src/test/kotlin/examples/kotlin/spring/canonical) |
70+
| Language | Runtime | Comments | Code Directory |
71+
|----------|------------------------------------------|------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
72+
| Java | MyBatis3 | Example using Java utility classes for MyBatis in the style of MyBatis Generator | [../examples/simple](src/test/java/examples/simple) |
73+
| Java | MyBatis3 + MyBatis-Spring | Example using MyBatis-Spring integration | [../examples/column/comparison](src/test/java/examples/column/comparison) |
74+
| Java | MyBatis3 + MyBatis-Spring (Spring Batch) | Example using Java utility classes for the MyBatis integration with Spring Batch | [../examples/springbatch](src/test/java/examples/springbatch) |
75+
| Java | Spring JDBC | Example using Java utility classes for Spring JDBC Template | [../examples/spring](src/test/java/examples/spring) |
76+
| Kotlin | MyBatis3 | Example using Kotlin utility classes for MyBatis in the style of MyBatis Generator | [../examples/kotlin/mybatis3/canonical](src/test/kotlin/examples/kotlin/mybatis3/canonical) |
77+
| Kotlin | MyBatis3 + MyBatis-Spring | Example using MyBatis-Spring integration in Kotlin | [../examples/kotlin/mybatis3/column/comparison](src/test/kotlin/examples/kotlin/mybatis3/column/comparison) |
78+
| Kotlin | Spring JDBC | Example using Kotlin utility classes for Spring JDBC Template | [../examples/kotlin/spring/canonical](src/test/kotlin/examples/kotlin/spring/canonical) |
6979

7080

7181
## Requirements

src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ protected AbstractListValueCondition(Collection<T> values) {
3232
this.values = Objects.requireNonNull(values);
3333
}
3434

35-
public final <R> Stream<R> mapValues(Function<T, R> mapper) {
36-
return values.stream().map(mapper);
35+
public final Stream<T> values() {
36+
return values.stream();
3737
}
3838

3939
@Override

src/main/java/org/mybatis/dynamic/sql/common/OrderByModel.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Collection;
2020
import java.util.List;
2121
import java.util.Objects;
22-
import java.util.function.Function;
2322
import java.util.stream.Stream;
2423

2524
import org.mybatis.dynamic.sql.SortSpecification;
@@ -34,8 +33,8 @@ private OrderByModel(Collection<? extends SortSpecification> columns) {
3433
this.columns.addAll(columns);
3534
}
3635

37-
public <R> Stream<R> mapColumns(Function<SortSpecification, R> mapper) {
38-
return columns.stream().map(mapper);
36+
public Stream<SortSpecification> columns() {
37+
return columns.stream();
3938
}
4039

4140
public static OrderByModel of(Collection<? extends SortSpecification> columns) {

src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
public class OrderByRenderer {
2424
public FragmentAndParameters render(OrderByModel orderByModel) {
25-
String phrase = orderByModel.mapColumns(this::calculateOrderByPhrase)
25+
String phrase = orderByModel.columns()
26+
.map(this::calculateOrderByPhrase)
2627
.collect(Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2728
return FragmentAndParameters.fromFragment(phrase);
2829
}

src/main/java/org/mybatis/dynamic/sql/insert/AbstractMultiRowInsertModel.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.Collections;
2121
import java.util.List;
2222
import java.util.Objects;
23-
import java.util.function.Function;
2423
import java.util.stream.Stream;
2524

2625
import org.mybatis.dynamic.sql.SqlTable;
@@ -37,8 +36,8 @@ protected AbstractMultiRowInsertModel(AbstractBuilder<T, ?> builder) {
3736
columnMappings = Objects.requireNonNull(builder.columnMappings);
3837
}
3938

40-
public <R> Stream<R> mapColumnMappings(Function<AbstractColumnMapping, R> mapper) {
41-
return columnMappings.stream().map(mapper);
39+
public Stream<AbstractColumnMapping> columnMappings() {
40+
return columnMappings.stream();
4241
}
4342

4443
public List<T> records() {

src/main/java/org/mybatis/dynamic/sql/insert/GeneralInsertModel.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.ArrayList;
1919
import java.util.List;
2020
import java.util.Objects;
21-
import java.util.function.Function;
2221
import java.util.stream.Stream;
2322

2423
import org.jetbrains.annotations.NotNull;
@@ -43,8 +42,8 @@ private GeneralInsertModel(Builder builder) {
4342
statementConfiguration = Objects.requireNonNull(builder.statementConfiguration);
4443
}
4544

46-
public <R> Stream<R> mapColumnMappings(Function<AbstractColumnMapping, R> mapper) {
47-
return insertMappings.stream().map(mapper);
45+
public Stream<AbstractColumnMapping> columnMappings() {
46+
return insertMappings.stream();
4847
}
4948

5049
public SqlTable table() {

src/main/java/org/mybatis/dynamic/sql/insert/InsertColumnListModel.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.ArrayList;
1919
import java.util.List;
2020
import java.util.Objects;
21-
import java.util.function.Function;
2221
import java.util.stream.Stream;
2322

2423
import org.mybatis.dynamic.sql.SqlColumn;
@@ -33,8 +32,9 @@ private InsertColumnListModel(List<SqlColumn<?>> columns) {
3332
this.columns.addAll(columns);
3433
}
3534

36-
public <R> Stream<R> mapColumns(Function<SqlColumn<?>, R> mapper) {
37-
return columns.stream().map(mapper);
35+
@SuppressWarnings("java:S1452")
36+
public Stream<SqlColumn<?>> columns() {
37+
return columns.stream();
3838
}
3939

4040
public static InsertColumnListModel of(List<SqlColumn<?>> columns) {

src/main/java/org/mybatis/dynamic/sql/insert/InsertModel.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.ArrayList;
1919
import java.util.List;
2020
import java.util.Objects;
21-
import java.util.function.Function;
2221
import java.util.stream.Stream;
2322

2423
import org.jetbrains.annotations.NotNull;
@@ -41,8 +40,8 @@ private InsertModel(Builder<T> builder) {
4140
Validator.assertNotEmpty(columnMappings, "ERROR.7"); //$NON-NLS-1$
4241
}
4342

44-
public <R> Stream<R> mapColumnMappings(Function<AbstractColumnMapping, R> mapper) {
45-
return columnMappings.stream().map(mapper);
43+
public Stream<AbstractColumnMapping> columnMappings() {
44+
return columnMappings.stream();
4645
}
4746

4847
public T row() {

src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsertRenderer.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@
2323
public class BatchInsertRenderer<T> {
2424

2525
private final BatchInsertModel<T> model;
26-
private final RenderingStrategy renderingStrategy;
26+
private final MultiRowValuePhraseVisitor visitor;
2727

2828
private BatchInsertRenderer(Builder<T> builder) {
2929
model = Objects.requireNonNull(builder.model);
30-
renderingStrategy = Objects.requireNonNull(builder.renderingStrategy);
30+
visitor = new MultiRowValuePhraseVisitor(builder.renderingStrategy, "row"); //$NON-NLS-1$)
3131
}
3232

3333
public BatchInsert<T> render() {
34-
MultiRowValuePhraseVisitor visitor = new MultiRowValuePhraseVisitor(renderingStrategy, "row"); //$NON-NLS-1$)
35-
FieldAndValueCollector collector = model.mapColumnMappings(m -> m.accept(visitor))
34+
FieldAndValueCollector collector = model.columnMappings()
35+
.map(m -> m.accept(visitor))
3636
.collect(FieldAndValueCollector.collect());
3737

3838
String insertStatement = InsertRenderingUtilities.calculateInsertStatement(model.table(), collector);

src/main/java/org/mybatis/dynamic/sql/insert/render/GeneralInsertRenderer.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,19 @@
2727
public class GeneralInsertRenderer {
2828

2929
private final GeneralInsertModel model;
30-
private final RenderingContext renderingContext;
30+
private final GeneralInsertValuePhraseVisitor visitor;
3131

3232
private GeneralInsertRenderer(Builder builder) {
3333
model = Objects.requireNonNull(builder.model);
34-
renderingContext = RenderingContext.withRenderingStrategy(builder.renderingStrategy)
34+
RenderingContext renderingContext = RenderingContext.withRenderingStrategy(builder.renderingStrategy)
3535
.withStatementConfiguration(builder.statementConfiguration)
3636
.build();
37+
visitor = new GeneralInsertValuePhraseVisitor(renderingContext);
3738
}
3839

3940
public GeneralInsertStatementProvider render() {
40-
GeneralInsertValuePhraseVisitor visitor = new GeneralInsertValuePhraseVisitor(renderingContext);
41-
FieldAndValueCollector collector = model.mapColumnMappings(m -> m.accept(visitor))
41+
FieldAndValueCollector collector = model.columnMappings()
42+
.map(m -> m.accept(visitor))
4243
.filter(Optional::isPresent)
4344
.map(Optional::get)
4445
.collect(FieldAndValueCollector.collect());

src/main/java/org/mybatis/dynamic/sql/insert/render/GeneralInsertValuePhraseVisitor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ private Optional<FieldAndValueAndParameters> buildNullFragment(AbstractColumnMap
8585
}
8686

8787
private Optional<FieldAndValueAndParameters> buildFragment(AbstractColumnMapping mapping, Object value) {
88-
RenderedParameterInfo parameterInfo = mapping.mapColumn(renderingContext::calculateParameterInfo);
88+
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo(mapping.column());
8989

9090
return FieldAndValueAndParameters.withFieldName(mapping.columnName())
9191
.withValuePhrase(parameterInfo.renderedPlaceHolder())

src/main/java/org/mybatis/dynamic/sql/insert/render/InsertRenderer.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,16 @@
2525
public class InsertRenderer<T> {
2626

2727
private final InsertModel<T> model;
28-
private final RenderingStrategy renderingStrategy;
28+
private final ValuePhraseVisitor visitor;
2929

3030
private InsertRenderer(Builder<T> builder) {
3131
model = Objects.requireNonNull(builder.model);
32-
renderingStrategy = Objects.requireNonNull(builder.renderingStrategy);
32+
visitor = new ValuePhraseVisitor(builder.renderingStrategy);
3333
}
3434

3535
public InsertStatementProvider<T> render() {
36-
ValuePhraseVisitor visitor = new ValuePhraseVisitor(renderingStrategy);
37-
38-
FieldAndValueCollector collector = model.mapColumnMappings(m -> m.accept(visitor))
36+
FieldAndValueCollector collector = model.columnMappings()
37+
.map(m -> m.accept(visitor))
3938
.filter(Optional::isPresent)
4039
.map(Optional::get)
4140
.collect(FieldAndValueCollector.collect());

src/main/java/org/mybatis/dynamic/sql/insert/render/InsertSelectRenderer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ private Optional<String> calculateColumnsPhrase() {
6363
}
6464

6565
private String calculateColumnsPhrase(InsertColumnListModel columnList) {
66-
return columnList.mapColumns(SqlColumn::name)
66+
return columnList.columns()
67+
.map(SqlColumn::name)
6768
.collect(Collectors.joining(", ", "(", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
6869
}
6970

0 commit comments

Comments
 (0)