Skip to content

Commit d819167

Browse files
authored
Merge pull request #861 from jeffgbutler/rework-spring-batch
Improve Spring Batch Support
2 parents f3b0725 + cfb47bc commit d819167

19 files changed

+386
-258
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ worked to make these changes as minimal as possible.
1212

1313
**Potentially Breaking Changes:**
1414

15+
- If you use this library with MyBatis' Spring Batch integration, you will need to make changes as we have
16+
refactored that support to be more flexible. Please see the
17+
[Spring Batch](https://mybatis.org/mybatis-dynamic-sql/docs/springBatch.html) documentation page to see the new usage
18+
details.
1519
- If you have created any custom implementations of `SortSpecification`, you will need to update those
1620
implementations due to a new rendering strategy for ORDER BY phrases. The old methods `isDescending` and `orderByName`
1721
are removed in favor of a new method `renderForOrderBy`

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
<properties>
5959
<java.version>17</java.version>
6060
<java.release.version>17</java.release.version>
61+
<java.test.version>17</java.test.version>
62+
<java.test.release.version>17</java.test.release.version>
6163
<junit.jupiter.version>5.11.3</junit.jupiter.version>
6264
<spring.batch.version>5.1.2</spring.batch.version>
6365

src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private Optional<FragmentAndParameters> calculateLimitClause() {
8484
}
8585

8686
private FragmentAndParameters renderLimitClause(Long limit) {
87-
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo();
87+
RenderedParameterInfo parameterInfo = renderingContext.calculateLimitParameterInfo();
8888

8989
return FragmentAndParameters.withFragment("limit " + parameterInfo.renderedPlaceHolder()) //$NON-NLS-1$
9090
.withParameter(parameterInfo.parameterMapKey(), limit)

src/main/java/org/mybatis/dynamic/sql/render/RenderingContext.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,27 @@ private String nextMapKey() {
5757
return renderingStrategy.formatParameterMapKey(sequence);
5858
}
5959

60-
private String renderedPlaceHolder(String mapKey) {
61-
return renderingStrategy.getFormattedJdbcPlaceholder(calculatedParameterName, mapKey);
62-
}
63-
6460
private <T> String renderedPlaceHolder(String mapKey, BindableColumn<T> column) {
6561
return column.renderingStrategy().orElse(renderingStrategy)
6662
.getFormattedJdbcPlaceholder(column, calculatedParameterName, mapKey);
6763
}
6864

69-
public RenderedParameterInfo calculateParameterInfo() {
70-
String mapKey = nextMapKey();
71-
return new RenderedParameterInfo(mapKey, renderedPlaceHolder(mapKey));
65+
public RenderedParameterInfo calculateFetchFirstRowsParameterInfo() {
66+
String mapKey = renderingStrategy.formatParameterMapKeyForFetchFirstRows(sequence);
67+
return new RenderedParameterInfo(mapKey,
68+
renderingStrategy.getFormattedJdbcPlaceholderForPagingParameters(calculatedParameterName, mapKey));
69+
}
70+
71+
public RenderedParameterInfo calculateLimitParameterInfo() {
72+
String mapKey = renderingStrategy.formatParameterMapKeyForLimit(sequence);
73+
return new RenderedParameterInfo(mapKey,
74+
renderingStrategy.getFormattedJdbcPlaceholderForPagingParameters(calculatedParameterName, mapKey));
75+
}
76+
77+
public RenderedParameterInfo calculateOffsetParameterInfo() {
78+
String mapKey = renderingStrategy.formatParameterMapKeyForOffset(sequence);
79+
return new RenderedParameterInfo(mapKey,
80+
renderingStrategy.getFormattedJdbcPlaceholderForPagingParameters(calculatedParameterName, mapKey));
7281
}
7382

7483
public <T> RenderedParameterInfo calculateParameterInfo(BindableColumn<T> column) {

src/main/java/org/mybatis/dynamic/sql/render/RenderingStrategy.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,55 @@
3636
public abstract class RenderingStrategy {
3737
public static final String DEFAULT_PARAMETER_PREFIX = "parameters"; //$NON-NLS-1$
3838

39+
/**
40+
* Generate a unique key that can be used to place a parameter value in the parameter map.
41+
*
42+
* @param sequence a sequence for calculating a unique value
43+
* @return a key used to place the parameter value in the parameter map
44+
*/
3945
public String formatParameterMapKey(AtomicInteger sequence) {
4046
return "p" + sequence.getAndIncrement(); //$NON-NLS-1$
4147
}
4248

49+
/**
50+
* Return a parameter map key intended as a parameter for a fetch first query.
51+
*
52+
* <p>By default, this parameter is treated the same as any other. This method is a hook to support
53+
* MyBatis Spring Batch.
54+
*
55+
* @param sequence a sequence for calculating a unique value
56+
* @return a key used to place the parameter value in the parameter map
57+
*/
58+
public String formatParameterMapKeyForFetchFirstRows(AtomicInteger sequence) {
59+
return formatParameterMapKey(sequence);
60+
}
61+
62+
/**
63+
* Return a parameter map key intended as a parameter for a limit query.
64+
*
65+
* <p>By default, this parameter is treated the same as any other. This method is a hook to support
66+
* MyBatis Spring Batch.
67+
*
68+
* @param sequence a sequence for calculating a unique value
69+
* @return a key used to place the parameter value in the parameter map
70+
*/
71+
public String formatParameterMapKeyForLimit(AtomicInteger sequence) {
72+
return formatParameterMapKey(sequence);
73+
}
74+
75+
/**
76+
* Return a parameter map key intended as a parameter for a query offset.
77+
*
78+
* <p>By default, this parameter is treated the same as any other. This method is a hook to support
79+
* MyBatis Spring Batch.
80+
*
81+
* @param sequence a sequence for calculating a unique value
82+
* @return a key used to place the parameter value in the parameter map
83+
*/
84+
public String formatParameterMapKeyForOffset(AtomicInteger sequence) {
85+
return formatParameterMapKey(sequence);
86+
}
87+
4388
/**
4489
* This method generates a binding for a parameter to a placeholder in a generated SQL statement.
4590
*
@@ -78,6 +123,23 @@ public String formatParameterMapKey(AtomicInteger sequence) {
78123
*/
79124
public abstract String getFormattedJdbcPlaceholder(String prefix, String parameterName);
80125

126+
/**
127+
* This method generates a binding for a parameter to a placeholder in a generated SQL statement.
128+
*
129+
* <p>This method is used to generate bindings for limit, offset, and fetch first parameters. By default, these
130+
* parameters are treated the same as any other. This method supports MyBatis Spring Batch integration where the
131+
* parameter keys have predefined values and need special handling.
132+
*
133+
* @param prefix parameter prefix used for locating the parameters in a SQL provider object. Typically, will be
134+
* {@link RenderingStrategy#DEFAULT_PARAMETER_PREFIX}. This is ignored for Spring.
135+
* @param parameterName name of the parameter. Typically generated by calling
136+
* {@link RenderingStrategy#formatParameterMapKey(AtomicInteger)}
137+
* @return the generated binding
138+
*/
139+
public String getFormattedJdbcPlaceholderForPagingParameters(String prefix, String parameterName) {
140+
return getFormattedJdbcPlaceholder(prefix, parameterName);
141+
}
142+
81143
/**
82144
* This method generates a binding for a parameter to a placeholder in a row based insert statement.
83145
*

src/main/java/org/mybatis/dynamic/sql/select/render/FetchFirstPagingModelRenderer.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,30 @@ private FragmentAndParameters renderFetchFirstRowsOnly() {
5151
}
5252

5353
private FragmentAndParameters renderFetchFirstRowsOnly(Long fetchFirstRows) {
54-
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo();
54+
RenderedParameterInfo fetchFirstParameterInfo = renderingContext.calculateFetchFirstRowsParameterInfo();
5555
return FragmentAndParameters
56-
.withFragment("fetch first " + parameterInfo.renderedPlaceHolder() //$NON-NLS-1$
56+
.withFragment("fetch first " + fetchFirstParameterInfo.renderedPlaceHolder() //$NON-NLS-1$
5757
+ " rows only") //$NON-NLS-1$
58-
.withParameter(parameterInfo.parameterMapKey(), fetchFirstRows)
58+
.withParameter(fetchFirstParameterInfo.parameterMapKey(), fetchFirstRows)
5959
.build();
6060
}
6161

6262
private FragmentAndParameters renderOffsetOnly(Long offset) {
63-
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo();
64-
return FragmentAndParameters.withFragment("offset " + parameterInfo.renderedPlaceHolder() //$NON-NLS-1$
63+
RenderedParameterInfo offsetParameterInfo = renderingContext.calculateOffsetParameterInfo();
64+
return FragmentAndParameters.withFragment("offset " + offsetParameterInfo.renderedPlaceHolder() //$NON-NLS-1$
6565
+ " rows") //$NON-NLS-1$
66-
.withParameter(parameterInfo.parameterMapKey(), offset)
66+
.withParameter(offsetParameterInfo.parameterMapKey(), offset)
6767
.build();
6868
}
6969

7070
private FragmentAndParameters renderOffsetAndFetchFirstRows(Long offset, Long fetchFirstRows) {
71-
RenderedParameterInfo parameterInfo1 = renderingContext.calculateParameterInfo();
72-
RenderedParameterInfo parameterInfo2 = renderingContext.calculateParameterInfo();
73-
return FragmentAndParameters.withFragment("offset " + parameterInfo1.renderedPlaceHolder() //$NON-NLS-1$
74-
+ " rows fetch first " + parameterInfo2.renderedPlaceHolder() //$NON-NLS-1$
71+
RenderedParameterInfo offsetParameterInfo = renderingContext.calculateOffsetParameterInfo();
72+
RenderedParameterInfo fetchFirstParameterInfo = renderingContext.calculateFetchFirstRowsParameterInfo();
73+
return FragmentAndParameters.withFragment("offset " + offsetParameterInfo.renderedPlaceHolder() //$NON-NLS-1$
74+
+ " rows fetch first " + fetchFirstParameterInfo.renderedPlaceHolder() //$NON-NLS-1$
7575
+ " rows only") //$NON-NLS-1$
76-
.withParameter(parameterInfo1.parameterMapKey(), offset)
77-
.withParameter(parameterInfo2.parameterMapKey(), fetchFirstRows)
76+
.withParameter(offsetParameterInfo.parameterMapKey(), offset)
77+
.withParameter(fetchFirstParameterInfo.parameterMapKey(), fetchFirstRows)
7878
.build();
7979
}
8080
}

src/main/java/org/mybatis/dynamic/sql/select/render/LimitAndOffsetPagingModelRenderer.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ public FragmentAndParameters render() {
4040
}
4141

4242
private FragmentAndParameters renderLimitOnly() {
43-
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo();
44-
return FragmentAndParameters.withFragment("limit " + parameterInfo.renderedPlaceHolder()) //$NON-NLS-1$
45-
.withParameter(parameterInfo.parameterMapKey(), limit)
43+
RenderedParameterInfo limitParameterInfo = renderingContext.calculateLimitParameterInfo();
44+
return FragmentAndParameters.withFragment("limit " + limitParameterInfo.renderedPlaceHolder()) //$NON-NLS-1$
45+
.withParameter(limitParameterInfo.parameterMapKey(), limit)
4646
.build();
4747
}
4848

4949
private FragmentAndParameters renderLimitAndOffset(Long offset) {
50-
RenderedParameterInfo parameterInfo1 = renderingContext.calculateParameterInfo();
51-
RenderedParameterInfo parameterInfo2 = renderingContext.calculateParameterInfo();
52-
return FragmentAndParameters.withFragment("limit " + parameterInfo1.renderedPlaceHolder() //$NON-NLS-1$
53-
+ " offset " + parameterInfo2.renderedPlaceHolder()) //$NON-NLS-1$
54-
.withParameter(parameterInfo1.parameterMapKey(), limit)
55-
.withParameter(parameterInfo2.parameterMapKey(), offset)
50+
RenderedParameterInfo limitParameterInfo = renderingContext.calculateLimitParameterInfo();
51+
RenderedParameterInfo offsetParameterInfo = renderingContext.calculateOffsetParameterInfo();
52+
return FragmentAndParameters.withFragment("limit " + limitParameterInfo.renderedPlaceHolder() //$NON-NLS-1$
53+
+ " offset " + offsetParameterInfo.renderedPlaceHolder()) //$NON-NLS-1$
54+
.withParameter(limitParameterInfo.parameterMapKey(), limit)
55+
.withParameter(offsetParameterInfo.parameterMapKey(), offset)
5656
.build();
5757
}
5858
}

src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private Optional<FragmentAndParameters> calculateLimitClause() {
109109
}
110110

111111
private FragmentAndParameters renderLimitClause(Long limit) {
112-
RenderedParameterInfo parameterInfo = renderingContext.calculateParameterInfo();
112+
RenderedParameterInfo parameterInfo = renderingContext.calculateLimitParameterInfo();
113113

114114
return FragmentAndParameters.withFragment("limit " + parameterInfo.renderedPlaceHolder()) //$NON-NLS-1$
115115
.withParameter(parameterInfo.parameterMapKey(), limit)

src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchCursorReaderSelectModel.java

Lines changed: 0 additions & 32 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2016-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.util.springbatch;
17+
18+
import java.util.concurrent.atomic.AtomicInteger;
19+
20+
import org.mybatis.dynamic.sql.render.MyBatis3RenderingStrategy;
21+
22+
/**
23+
* This rendering strategy should be used for MyBatis3 statements using the
24+
* MyBatisPagingItemReader supplied by mybatis-spring integration
25+
* (<a href="http://www.mybatis.org/spring/">http://www.mybatis.org/spring/</a>).
26+
*/
27+
public class SpringBatchPagingItemReaderRenderingStrategy extends MyBatis3RenderingStrategy {
28+
29+
@Override
30+
public String getFormattedJdbcPlaceholderForPagingParameters(String prefix, String parameterName) {
31+
return "#{" //$NON-NLS-1$
32+
+ parameterName
33+
+ "}"; //$NON-NLS-1$
34+
}
35+
36+
@Override
37+
public String formatParameterMapKeyForFetchFirstRows(AtomicInteger sequence) {
38+
return "_pagesize"; //$NON-NLS-1$
39+
}
40+
41+
@Override
42+
public String formatParameterMapKeyForLimit(AtomicInteger sequence) {
43+
return "_pagesize"; //$NON-NLS-1$
44+
}
45+
46+
@Override
47+
public String formatParameterMapKeyForOffset(AtomicInteger sequence) {
48+
return "_skiprows"; //$NON-NLS-1$
49+
}
50+
}

src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchPagingReaderSelectModel.java

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/main/java/org/mybatis/dynamic/sql/util/springbatch/SpringBatchProviderAdapter.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,9 @@
1717

1818
import java.util.Map;
1919

20-
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
21-
2220
public class SpringBatchProviderAdapter {
2321

2422
public String select(Map<String, Object> parameterValues) {
25-
SelectStatementProvider selectStatement =
26-
(SelectStatementProvider) parameterValues.get(SpringBatchUtility.PARAMETER_KEY);
27-
return selectStatement.getSelectStatement();
23+
return (String) parameterValues.get(SpringBatchUtility.PARAMETER_KEY);
2824
}
2925
}

0 commit comments

Comments
 (0)