如何为JdbcPollingChannelAdapter的更新参数设置非缓存SqlParameterSource
Great question! I’ve run into this exact asymmetry before when working with JdbcPollingChannelAdapter—it’s frustrating that select parameters let you pass a direct, non-cached SqlParameterSource, but updates are tied to a factory. Let’s break down the solution.
The Core Issue
By default, the ExpressionEvaluatingSqlParameterSourceFactory (the common factory for update parameters) caches the SqlParameterSource instance it creates. This works for static parameters, but if you need dynamic, per-poll update parameters (like you do with your non-cached select parameters), you need to disable this caching behavior.
Solution 1: Disable Caching in the Default Factory
The simplest fix is to configure the standard ExpressionEvaluatingSqlParameterSourceFactory to not cache its parameter sources. This makes it behave just like calling createParameterSourceNoCache() for your select parameters.
Java Configuration Example
// Create the factory and disable caching ExpressionEvaluatingSqlParameterSourceFactory updateParamFactory = new ExpressionEvaluatingSqlParameterSourceFactory(); updateParamFactory.setCacheEnabled(false); // This is the key line // Configure your adapter JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter(dataSource, "SELECT id, data FROM my_table WHERE status = :status"); adapter.setUpdateSql("UPDATE my_table SET status = 'PROCESSED' WHERE id = :id"); // Set the non-caching factory for updates adapter.setUpdateSqlParameterSourceFactory(updateParamFactory);
XML Configuration Example
<int-jdbc:inbound-channel-adapter id="jdbcPoller" query="SELECT id, data FROM my_table WHERE status = :status" update="UPDATE my_table SET status = 'PROCESSED' WHERE id = :id" data-source="dataSource"> <!-- Disable caching for update parameters --> <int-jdbc:update-sql-parameter-source-factory> <int-jdbc:expression-evaluating-sql-parameter-source-factory cache-enabled="false"/> </int-jdbc:update-sql-parameter-source-factory> </int-jdbc:inbound-channel-adapter>
When cacheEnabled is set to false, the factory will create a new SqlParameterSource instance every time the adapter runs an update, which matches the non-cached behavior you’re using for your select parameters.
Solution 2: Custom Factory for Full Control
If you need even more flexibility (like dynamically generating parameters based on the poll results or other context), you can create a custom SqlParameterSourceFactory that always returns a fresh instance:
public class DynamicUpdateParamFactory implements SqlParameterSourceFactory { @Override public SqlParameterSource createParameterSource(Object input) { // input will be the result of the select query (if using a row mapper, it's the mapped object) MyRecord record = (MyRecord) input; // Create a new parameter source every time, with dynamic values return new MapSqlParameterSource() .addValue("id", record.getId()) .addValue("processedTimestamp", LocalDateTime.now()); } }
Then attach it to your adapter:
adapter.setUpdateSqlParameterSourceFactory(new DynamicUpdateParamFactory());
This approach gives you full control over how update parameters are generated, with zero caching by default.
Wrap-Up
For most cases, disabling caching on the standard ExpressionEvaluatingSqlParameterSourceFactory is the quickest and cleanest solution. It aligns the update parameter behavior with your non-cached select parameters, ensuring you get fresh values on every poll.
内容的提问来源于stack exchange,提问作者Curtis Olson

