Skip to content

Commit 32030c3

Browse files
artembilangaryrussell
authored andcommitted
INT-2260: JdbcPollingChA: rename prop to maxRows
JIRA: https://jira.spring.io/browse/INT-2260 Having a feedback about confusing with the `max-rows-per-poll` property name and its responsibility it would be better do not mention `per-poll` at all * Deprecate `max-rows-per-poll` in favor of new `max-rows` * Some code style polishing, tests improvements * Docs polishing on the matter * Add `What's New` bullet * Optimize `maxRows` logic * Document vendor-specific native SELECT limiting options * Raise warning in the parsers about deprecated `max-rows-per-poll` Doc polishing
1 parent 5a362b6 commit 32030c3

File tree

12 files changed

+241
-152
lines changed

12 files changed

+241
-152
lines changed

spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -44,14 +44,13 @@ public class JdbcOutboundGateway extends AbstractReplyProducingMessageHandler im
4444

4545
private final JdbcPollingChannelAdapter poller;
4646

47-
private volatile SqlParameterSourceFactory sqlParameterSourceFactory =
48-
new ExpressionEvaluatingSqlParameterSourceFactory();
47+
private SqlParameterSourceFactory sqlParameterSourceFactory = new ExpressionEvaluatingSqlParameterSourceFactory();
4948

50-
private volatile boolean sqlParameterSourceFactorySet;
49+
private boolean sqlParameterSourceFactorySet;
5150

52-
private volatile boolean keysGenerated;
51+
private boolean keysGenerated;
5352

54-
private volatile Integer maxRowsPerPoll;
53+
private Integer maxRows;
5554

5655
public JdbcOutboundGateway(DataSource dataSource, String updateQuery) {
5756
this(new JdbcTemplate(dataSource), updateQuery, null);
@@ -66,16 +65,16 @@ public JdbcOutboundGateway(JdbcOperations jdbcOperations, String updateQuery) {
6665
}
6766

6867
public JdbcOutboundGateway(JdbcOperations jdbcOperations, String updateQuery, String selectQuery) {
69-
7068
Assert.notNull(jdbcOperations, "'jdbcOperations' must not be null.");
7169

7270
if (!StringUtils.hasText(updateQuery) && !StringUtils.hasText(selectQuery)) {
73-
throw new IllegalArgumentException("The 'updateQuery' and the 'selectQuery' must not both be null or empty.");
71+
throw new IllegalArgumentException(
72+
"The 'updateQuery' and the 'selectQuery' must not both be null or empty.");
7473
}
7574

7675
if (StringUtils.hasText(selectQuery)) {
7776
this.poller = new JdbcPollingChannelAdapter(jdbcOperations, selectQuery);
78-
this.poller.setMaxRowsPerPoll(1);
77+
this.poller.setMaxRows(1);
7978
}
8079
else {
8180
this.poller = null;
@@ -98,10 +97,54 @@ public JdbcOutboundGateway(JdbcOperations jdbcOperations, String updateQuery, St
9897
* This parameter is only applicable if a selectQuery was provided. Null values
9998
* are not permitted.
10099
* @param maxRowsPerPoll the number of rows to select. Must not be null.
100+
* @deprecated since 5.1 in favor of {@link #setMaxRows(Integer)}
101101
*/
102+
@Deprecated
102103
public void setMaxRowsPerPoll(Integer maxRowsPerPoll) {
103-
Assert.notNull(maxRowsPerPoll, "MaxRowsPerPoll must not be null.");
104-
this.maxRowsPerPoll = maxRowsPerPoll;
104+
setMaxRows(maxRowsPerPoll);
105+
}
106+
107+
/**
108+
* The maximum number of rows to query.
109+
* The value is ultimately set on the underlying {@link JdbcPollingChannelAdapter}.
110+
* If not specified this value will default to {@code 1}.
111+
* This parameter is only applicable if a selectQuery was provided. Null values
112+
* are not permitted.
113+
* @param maxRows the number of rows to select. Must not be null.
114+
* @since 5.1
115+
* @see JdbcPollingChannelAdapter#setMaxRows(int)
116+
*/
117+
public void setMaxRows(Integer maxRows) {
118+
Assert.notNull(maxRows, "'maxRows' must not be null.");
119+
this.maxRows = maxRows;
120+
}
121+
122+
/**
123+
* Flag to indicate that the update query is an insert with auto-generated keys,
124+
* which will be logged at debug level.
125+
* @param keysGenerated the flag value to set
126+
*/
127+
public void setKeysGenerated(boolean keysGenerated) {
128+
this.keysGenerated = keysGenerated;
129+
}
130+
131+
public void setRequestSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
132+
Assert.notNull(this.handler, "'handler' cannot be null");
133+
this.handler.setSqlParameterSourceFactory(sqlParameterSourceFactory);
134+
}
135+
136+
public void setRequestPreparedStatementSetter(MessagePreparedStatementSetter requestPreparedStatementSetter) {
137+
Assert.notNull(this.handler, "'handler' cannot be null");
138+
this.handler.setPreparedStatementSetter(requestPreparedStatementSetter);
139+
}
140+
141+
public void setReplySqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
142+
this.sqlParameterSourceFactory = sqlParameterSourceFactory;
143+
this.sqlParameterSourceFactorySet = true;
144+
}
145+
146+
public void setRowMapper(RowMapper<?> rowMapper) {
147+
this.poller.setRowMapper(rowMapper);
105148
}
106149

107150
@Override
@@ -111,9 +154,9 @@ public String getComponentType() {
111154

112155
@Override
113156
protected void doInit() {
114-
if (this.maxRowsPerPoll != null) {
115-
Assert.notNull(this.poller, "If you want to set 'maxRowsPerPoll', then you must provide a 'selectQuery'.");
116-
this.poller.setMaxRowsPerPoll(this.maxRowsPerPoll);
157+
if (this.maxRows != null) {
158+
Assert.notNull(this.poller, "If you want to set 'maxRows', then you must provide a 'selectQuery'.");
159+
this.poller.setMaxRows(this.maxRows);
117160
}
118161

119162
if (this.handler != null) {
@@ -167,31 +210,4 @@ protected Object handleRequestMessage(Message<?> requestMessage) {
167210
return payload;
168211
}
169212

170-
/**
171-
* Flag to indicate that the update query is an insert with auto-generated keys, which will be logged at debug level.
172-
* @param keysGenerated the flag value to set
173-
*/
174-
public void setKeysGenerated(boolean keysGenerated) {
175-
this.keysGenerated = keysGenerated;
176-
}
177-
178-
public void setRequestSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
179-
Assert.notNull(this.handler, "'handler' cannot be null");
180-
this.handler.setSqlParameterSourceFactory(sqlParameterSourceFactory);
181-
}
182-
183-
public void setRequestPreparedStatementSetter(MessagePreparedStatementSetter requestPreparedStatementSetter) {
184-
Assert.notNull(this.handler, "'handler' cannot be null");
185-
this.handler.setPreparedStatementSetter(requestPreparedStatementSetter);
186-
}
187-
188-
public void setReplySqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
189-
this.sqlParameterSourceFactory = sqlParameterSourceFactory;
190-
this.sqlParameterSourceFactorySet = true;
191-
}
192-
193-
public void setRowMapper(RowMapper<?> rowMapper) {
194-
this.poller.setRowMapper(rowMapper);
195-
}
196-
197213
}

spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcPollingChannelAdapter.java

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,22 +16,25 @@
1616

1717
package org.springframework.integration.jdbc;
1818

19-
import java.util.ArrayList;
19+
import java.sql.PreparedStatement;
2020
import java.util.List;
21+
import java.util.function.Consumer;
2122

2223
import javax.sql.DataSource;
2324

2425
import org.springframework.integration.context.IntegrationObjectSupport;
2526
import org.springframework.integration.core.MessageSource;
2627
import org.springframework.jdbc.core.ColumnMapRowMapper;
2728
import org.springframework.jdbc.core.JdbcOperations;
28-
import org.springframework.jdbc.core.ResultSetExtractor;
29+
import org.springframework.jdbc.core.JdbcTemplate;
30+
import org.springframework.jdbc.core.PreparedStatementCreator;
31+
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
2932
import org.springframework.jdbc.core.RowMapper;
30-
import org.springframework.jdbc.core.RowMapperResultSetExtractor;
3133
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
3234
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
3335
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
3436
import org.springframework.messaging.Message;
37+
import org.springframework.util.Assert;
3538

3639
/**
3740
* A polling channel adapter that creates messages from the payload returned by
@@ -50,42 +53,55 @@ public class JdbcPollingChannelAdapter extends IntegrationObjectSupport implemen
5053

5154
private final String selectQuery;
5255

53-
private volatile RowMapper<?> rowMapper;
56+
private RowMapper<?> rowMapper;
5457

55-
private volatile SqlParameterSource sqlQueryParameterSource;
58+
private SqlParameterSource sqlQueryParameterSource;
5659

57-
private volatile boolean updatePerRow = false;
60+
private boolean updatePerRow = false;
5861

59-
private volatile String updateSql;
62+
private String updateSql;
6063

61-
private volatile SqlParameterSourceFactory sqlParameterSourceFactory =
62-
new ExpressionEvaluatingSqlParameterSourceFactory();
64+
private SqlParameterSourceFactory sqlParameterSourceFactory = new ExpressionEvaluatingSqlParameterSourceFactory();
6365

64-
private volatile boolean sqlParameterSourceFactorySet;
66+
private boolean sqlParameterSourceFactorySet;
6567

66-
private volatile int maxRowsPerPoll = 0;
68+
private int maxRows = 0;
6769

6870
/**
6971
* Constructor taking {@link DataSource} from which the DB Connection can be
7072
* obtained and the select query to execute to retrieve new rows.
71-
*
7273
* @param dataSource Must not be null
7374
* @param selectQuery query to execute
7475
*/
7576
public JdbcPollingChannelAdapter(DataSource dataSource, String selectQuery) {
76-
this.jdbcOperations = new NamedParameterJdbcTemplate(dataSource);
77-
this.selectQuery = selectQuery;
77+
this(new JdbcTemplate(dataSource), selectQuery);
7878
}
7979

8080
/**
8181
* Constructor taking {@link JdbcOperations} instance to use for query
8282
* execution and the select query to execute to retrieve new rows.
83-
*
8483
* @param jdbcOperations instance to use for query execution
8584
* @param selectQuery query to execute
8685
*/
8786
public JdbcPollingChannelAdapter(JdbcOperations jdbcOperations, String selectQuery) {
88-
this.jdbcOperations = new NamedParameterJdbcTemplate(jdbcOperations);
87+
Assert.hasText(selectQuery, "'selectQuery' must be specified.");
88+
this.jdbcOperations = new NamedParameterJdbcTemplate(jdbcOperations) {
89+
90+
@Override
91+
protected PreparedStatementCreator getPreparedStatementCreator(String sql,
92+
SqlParameterSource paramSource, Consumer<PreparedStatementCreatorFactory> customizer) {
93+
94+
PreparedStatementCreator preparedStatementCreator =
95+
super.getPreparedStatementCreator(sql, paramSource, customizer);
96+
97+
return con -> {
98+
PreparedStatement preparedStatement = preparedStatementCreator.createPreparedStatement(con);
99+
preparedStatement.setMaxRows(JdbcPollingChannelAdapter.this.maxRows);
100+
return preparedStatement;
101+
};
102+
}
103+
};
104+
89105
this.selectQuery = selectQuery;
90106
}
91107

@@ -108,7 +124,6 @@ public void setUpdateSqlParameterSourceFactory(SqlParameterSourceFactory sqlPara
108124

109125
/**
110126
* A source of parameters for the select query used for polling.
111-
*
112127
* @param sqlQueryParameterSource the sql query parameter source to set
113128
*/
114129
public void setSelectSqlParameterSource(SqlParameterSource sqlQueryParameterSource) {
@@ -119,22 +134,37 @@ public void setSelectSqlParameterSource(SqlParameterSource sqlQueryParameterSour
119134
* The maximum number of rows to pull out of the query results per poll (if
120135
* greater than zero, otherwise all rows will be packed into the outgoing
121136
* message). Default is zero.
122-
*
123137
* @param maxRows the max rows to set
138+
* @deprecated since 5.1 in favor of {@link #setMaxRows(int)}
124139
*/
140+
@Deprecated
125141
public void setMaxRowsPerPoll(int maxRows) {
126-
this.maxRowsPerPoll = maxRows;
142+
setMaxRows(maxRows);
143+
}
144+
145+
/**
146+
* The maximum number of rows to query. Default is zero - select all records.
147+
* @param maxRows the max rows to set
148+
* @since 5.1
149+
*/
150+
public void setMaxRows(int maxRows) {
151+
this.maxRows = maxRows;
127152
}
128153

129154
@Override
130155
protected void onInit() throws Exception {
131156
super.onInit();
132-
if (!this.sqlParameterSourceFactorySet && this.getBeanFactory() != null) {
157+
if (!this.sqlParameterSourceFactorySet && getBeanFactory() != null) {
133158
((ExpressionEvaluatingSqlParameterSourceFactory) this.sqlParameterSourceFactory)
134-
.setBeanFactory(this.getBeanFactory());
159+
.setBeanFactory(getBeanFactory());
135160
}
136161
}
137162

163+
@Override
164+
public String getComponentType() {
165+
return "jdbc:inbound-channel-adapter";
166+
}
167+
138168
/**
139169
* Execute the query. If a query result set contains one or more rows, the
140170
* Message payload will contain either a List of Maps for each row or, if a
@@ -148,7 +178,9 @@ public Message<Object> receive() {
148178
if (payload == null) {
149179
return null;
150180
}
151-
return this.getMessageBuilderFactory().withPayload(payload).build();
181+
return getMessageBuilderFactory()
182+
.withPayload(payload)
183+
.build();
152184
}
153185

154186
/**
@@ -174,43 +206,20 @@ private Object poll() {
174206
return payload;
175207
}
176208

177-
private void executeUpdateQuery(Object obj) {
178-
SqlParameterSource updateParameterSource = this.sqlParameterSourceFactory.createParameterSource(obj);
179-
this.jdbcOperations.update(this.updateSql, updateParameterSource);
180-
}
181-
182209
protected List<?> doPoll(SqlParameterSource sqlQueryParameterSource) {
183210
final RowMapper<?> rowMapper = this.rowMapper == null ? new ColumnMapRowMapper() : this.rowMapper;
184-
ResultSetExtractor<List<Object>> resultSetExtractor;
185-
186-
if (this.maxRowsPerPoll > 0) {
187-
resultSetExtractor = rs -> {
188-
List<Object> results = new ArrayList<Object>(JdbcPollingChannelAdapter.this.maxRowsPerPoll);
189-
int rowNum = 0;
190-
while (rs.next() && rowNum < JdbcPollingChannelAdapter.this.maxRowsPerPoll) {
191-
results.add(rowMapper.mapRow(rs, rowNum++));
192-
}
193-
return results;
194-
};
195-
}
196-
else {
197-
@SuppressWarnings("unchecked")
198-
ResultSetExtractor<List<Object>> temp =
199-
new RowMapperResultSetExtractor<Object>((RowMapper<Object>) rowMapper);
200-
resultSetExtractor = temp;
201-
}
202211

203212
if (sqlQueryParameterSource != null) {
204-
return this.jdbcOperations.query(this.selectQuery, sqlQueryParameterSource, resultSetExtractor);
213+
return this.jdbcOperations.query(this.selectQuery, sqlQueryParameterSource, rowMapper);
205214
}
206215
else {
207-
return this.jdbcOperations.getJdbcOperations().query(this.selectQuery, resultSetExtractor);
216+
return this.jdbcOperations.query(this.selectQuery, rowMapper);
208217
}
209218
}
210219

211-
@Override
212-
public String getComponentType() {
213-
return "jdbc:inbound-channel-adapter";
220+
private void executeUpdateQuery(Object obj) {
221+
SqlParameterSource updateParameterSource = this.sqlParameterSourceFactory.createParameterSource(obj);
222+
this.jdbcOperations.update(this.updateSql, updateParameterSource);
214223
}
215224

216225
}

0 commit comments

Comments
 (0)