INT-1173: added sql parameter source support

This commit is contained in:
David Syer
2010-06-14 09:46:54 +00:00
parent ceb4036b38
commit 986a383450
12 changed files with 313 additions and 173 deletions

View File

@@ -28,49 +28,81 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* A default implementation of {@link SqlParameterSourceFactory} which creates an {@link SqlParameterSource} according
* to the result of the data passed in.
* to the type of the data passed in.
*
* <ul>
* <li>
* Where the data is a List, a list of ids is generated by looking for a map entry or bean property named by default
* 'id'. The resulting {@link SqlParameterSource} contains this list under a default key of 'idList'.
*
* Where the data is a {@link Map}, this is wrapped in an instance of {@link MapSqlParameterSource}.
* Otherwise the result is wrapped in an instance of {@link BeanPropertySqlParameterSource}.
* 'id'. The resulting {@link SqlParameterSource} is a map that contains this list under a default key of 'idList'.</li>
* <li>
* Where the data is a {@link Map}, this is wrapped in an instance of {@link MapSqlParameterSource}.</li>
* <li>
* Otherwise the result is wrapped in a {@link BeanPropertySqlParameterSource}.</li>
* </ul>
*
* @author Jonas Partner
* @author Dave Syer
* @since 2.0
*/
public class DefaultSqlParameterSourceFactory implements SqlParameterSourceFactory {
private final Log logger = LogFactory.getLog(getClass());
private final Map<String, Object> staticParameters;
private Map<String, Object> staticParameters;
private final String polledRowIdName = "id";
private String rowIdName = "id";
private final String updateIdsParamName = "idList";
private String idsParamName = "idList";
public DefaultSqlParameterSourceFactory() {
this.staticParameters = Collections.unmodifiableMap(new HashMap<String, Object>());
}
public DefaultSqlParameterSourceFactory(Map<String, Object> staticParameters) {
this.staticParameters = Collections.unmodifiableMap(staticParameters);
/**
* Name of the id property in the input elements when the input data is List. Defaults to "id".
* If the input is not a List then this value is ignored.
* @param rowIdName the name to set
*/
public void setRowIdName(String rowIdName) {
this.rowIdName = rowIdName;
}
/**
* Name of the id list in the output parameters if the input is a List (default "idList"). If the input is not a
* List then this value is ignored.
*
* @param idsParamName the name to set
*/
public void setIdsParameterName(String idsParamName) {
this.idsParamName = idsParamName;
}
/**
* If the input is a List or a Map, the output is a map parameter source, and in that case some static parameters
* can be added (default is empty). If the input is not a List or a Map then this value is ignored.
*
* @param staticParameters the static parameters to set
*/
public void setStaticParameters(Map<String, Object> staticParameters) {
this.staticParameters = staticParameters;
}
@SuppressWarnings("unchecked")
public SqlParameterSource createParameterSource(Object resultOfSelect) {
public SqlParameterSource createParameterSource(Object input) {
SqlParameterSource toReturn;
if (resultOfSelect instanceof List) {
if (input instanceof List) {
List<Object> ids = new ArrayList<Object>();
for (Object rowObj : (List) resultOfSelect) {
for (Object rowObj : (List) input) {
if (rowObj instanceof Map) {
ids.add(((Map) rowObj).get(this.polledRowIdName));
} else {
ids.add(((Map) rowObj).get(this.rowIdName));
}
else {
DirectFieldAccessor accessor = new DirectFieldAccessor(rowObj);
if (accessor.isReadableProperty(this.polledRowIdName)) {
ids.add(accessor.getPropertyValue(this.polledRowIdName));
} else {
logger.warn("No id field named '" + this.polledRowIdName
if (accessor.isReadableProperty(this.rowIdName)) {
ids.add(accessor.getPropertyValue(this.rowIdName));
}
else {
logger.warn("No id field named '" + this.rowIdName
+ "' found for result of polled row. Update may not include all rows.");
}
}
@@ -79,15 +111,17 @@ public class DefaultSqlParameterSourceFactory implements SqlParameterSourceFacto
if (this.staticParameters != null) {
thisParamSource.addValues(this.staticParameters);
}
thisParamSource.addValue(this.updateIdsParamName, ids);
thisParamSource.addValue(this.idsParamName, ids);
thisParamSource.getValue("idList");
toReturn = thisParamSource;
} else if (resultOfSelect instanceof Map) {
MapSqlParameterSource mapParameterSource = new MapSqlParameterSource((Map) resultOfSelect);
}
else if (input instanceof Map) {
MapSqlParameterSource mapParameterSource = new MapSqlParameterSource((Map) input);
mapParameterSource.addValues(this.staticParameters);
toReturn = mapParameterSource;
} else {
BeanPropertySqlParameterSource beanParameterSource = new BeanPropertySqlParameterSource(resultOfSelect);
}
else {
BeanPropertySqlParameterSource beanParameterSource = new BeanPropertySqlParameterSource(input);
toReturn = beanParameterSource;
}
return toReturn;

View File

@@ -51,7 +51,7 @@ public class JdbcPollingChannelAdapter implements MessageSource<Object> {
private volatile String updateSql;
private volatile SqlParameterSourceFactory sqlParameterSourceFactoryForUpdate = new DefaultSqlParameterSourceFactory();
private volatile SqlParameterSourceFactory sqlParameterSourceFactory = new DefaultSqlParameterSourceFactory();
/**
@@ -91,8 +91,8 @@ public class JdbcPollingChannelAdapter implements MessageSource<Object> {
this.updatePerRow = updatePerRow;
}
public void setSqlParameterSourceFactoryForUpdate(SqlParameterSourceFactory sqlParameterSourceFactoryForUpdate) {
this.sqlParameterSourceFactoryForUpdate = sqlParameterSourceFactoryForUpdate;
public void setSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.sqlParameterSourceFactory = sqlParameterSourceFactory;
}
/**
@@ -102,7 +102,7 @@ public class JdbcPollingChannelAdapter implements MessageSource<Object> {
* this method will return <code>null</code>.
*/
public Message<Object> receive() {
Object payload = pollAndUpdate();
Object payload = poll();
if (payload == null) {
return null;
}
@@ -114,7 +114,7 @@ public class JdbcPollingChannelAdapter implements MessageSource<Object> {
* Returns the rows returned by the select query. If a RowMapper
* has been provided, the mapped results are returned.
*/
private Object pollAndUpdate() {
private Object poll() {
List<?> payload;
if (this.rowMapper != null) {
payload = pollWithRowMapper();
@@ -140,8 +140,8 @@ public class JdbcPollingChannelAdapter implements MessageSource<Object> {
private void executeUpdateQuery(Object obj) {
SqlParameterSource updateParamaterSource = null;
if (this.sqlParameterSourceFactoryForUpdate != null) {
updateParamaterSource = this.sqlParameterSourceFactoryForUpdate.createParameterSource(obj);
if (this.sqlParameterSourceFactory != null) {
updateParamaterSource = this.sqlParameterSourceFactory.createParameterSource(obj);
this.jdbcOperations.update(this.updateSql, updateParamaterSource);
}
else {

View File

@@ -19,9 +19,8 @@ package org.springframework.integration.jdbc;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* Collaborator for {@link JdbcPollingChannelAdapter} which allows creation of
* instances of {@link SqlParameterSource} for use in updates to be created
* according to the result of the poll.
* Collaborator for JDBC adapters which allows creation of
* instances of {@link SqlParameterSource} for use in update operations.
*
* @author Jonas Partner
* @since 2.0
@@ -30,8 +29,8 @@ public interface SqlParameterSourceFactory {
/**
* Return a new {@link SqlParameterSource}.
* @param resultOfSelect the result of the preceding poll operation
* @param input the raw message or query result to be transformed into a SqlParameterSource
*/
public SqlParameterSource createParameterSource(Object resultOfSelect);
public SqlParameterSource createParameterSource(Object input);
}

View File

@@ -18,6 +18,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -60,6 +61,7 @@ public class JdbcMessageHandlerParser extends AbstractOutboundChannelAdapterPars
} else {
builder.addConstructorArgReference(jdbcOperationsRef);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "sql-parameter-source-factory");
builder.addConstructorArgValue(query);
return builder.getBeanDefinition();
}

View File

@@ -67,6 +67,7 @@ public class JdbcPollingChannelAdapterParser extends AbstractPollingInboundChann
}
builder.addConstructorArgValue(query);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "row-mapper");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "sql-parameter-source-factory");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "update", "updateSql");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "update-per-row");
return BeanDefinitionReaderUtils.registerWithGeneratedName(

View File

@@ -1,15 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/jdbc"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/jdbc"
<xsd:schema xmlns="http://www.springframework.org/schema/integration/jdbc" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration" targetNamespace="http://www.springframework.org/schema/integration/jdbc"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd" />
<xsd:import namespace="http://www.springframework.org/schema/integration" schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd" />
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -31,7 +28,8 @@
<xsd:annotation>
<xsd:documentation>
Reference to a data source to use to access
the database. Either this or the jdbc-operations must be
the database. Either this or the jdbc-operations
must be
specified (but not both).
</xsd:documentation>
<xsd:appinfo>
@@ -51,8 +49,7 @@
specified (but not both).
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.jdbc.core.JdbcOperations" />
<tool:expected-type type="org.springframework.jdbc.core.JdbcOperations" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -62,7 +59,8 @@
<xsd:documentation>
Unique string to use as a partition for the
data in this store, so that
multiple instances can share the same
multiple instances can
share the same
database tables. The default
is "DEFAULT".
</xsd:documentation>
@@ -72,7 +70,8 @@
<xsd:annotation>
<xsd:documentation>
Prefix for the table names in the database
(e.g. so that a schema can be specified, or to avoid a clash
(e.g. so that a schema can be specified, or to avoid
a clash
with
other tables). The default is "INT_".
</xsd:documentation>
@@ -86,8 +85,7 @@
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.jdbc.support.lob.LobHandler" />
<tool:expected-type type="org.springframework.jdbc.support.lob.LobHandler" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
@@ -105,64 +103,74 @@
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0"
maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="data-source" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Reference to a data source to use to access
the
database. Either this or the simple-jdbc-operations must be
specified (but not both).
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="javax.sql.DataSource" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="jdbc-operations" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a JdbcOperations. Either
this or
the data-source must be
specified (but not both).
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.jdbc.core.JdbcOperations" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="query" type="xsd:string" use="required" />
<xsd:attribute name="row-mapper" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.jdbc.core.RowMapper" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="update" type="xsd:string" />
<xsd:attribute name="update-per-row" type="xsd:boolean"
default="false" />
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:complexContent>
<xsd:extension base="jdbcType">
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="query" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
A select query to execute when a message is polled. In general the query can return multiple
rows, because the result will be a List (of type determined by the row mapper).
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="row-mapper" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a row mapper to use to convert JDBC result set rows to message payloads.
Optional
with default that maps
result set row to a map (column name to column value). Other simple
use cases can
be handled
with out-of-the box implementations from Spring JDBC. Others require a custom row
mapper.
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.jdbc.core.RowMapper" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="update" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
An update query to execute when a message is polled. If the poll is in a transaction then the
update will roll back if the transaction does.
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="update-per-row" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Flag to indicate whether the update query should be executed per message, or per row (in the
case that a message contains multiple rows).
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Channel to which polled messages will be sent.
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
@@ -174,59 +182,88 @@
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="data-source" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Reference to a data source to use to access
the
database. Either this or the simple-jdbc-operations must be
specified (but not both).
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="javax.sql.DataSource" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="jdbc-operations" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a JdbcOperations. Either
this or
the data-source must be
specified (but not both).
<xsd:complexContent>
<xsd:extension base="jdbcType">
<xsd:attribute name="query" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
An SQL update query to execute (INSERT, UPDATE
or DELETE). Bean properties of the outgoing
message can be
referenced in named parameters, e.g. "INSERT into FOOS (ID, NAME) values (:headers[business.key],
:payload)". More complex requirements can be implemented by
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.jdbc.core.JdbcOperations" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="query" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
An SQL update query to execute (INSERT, UPDATE
or DELETE). Bean properties of the outgoing message can be
referenced in named parameters, e.g. "INSERT into FOOS (ID, NAME) values (:headers[business.key], :payload)"
</xsd:documentation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Channel from which messages will be output. When a message is sent to this channel it will
cause the query to be executed.
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="jdbcType">
<xsd:attribute name="data-source" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Reference to a data source to use to access
the
database. Either this or the
simple-jdbc-operations
must be
specified (but not both).
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="javax.sql.DataSource" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="jdbc-operations" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a JdbcOperations. Either
this or
the data-source must be
specified (but not both).
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.jdbc.core.JdbcOperations" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="sql-parameter-source-factory" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<xsd:documentation>
Reference to a SqlParameterSourceFactory. For an inbound adapter the input is the result of the
query, and for an outbound adapter the input is the whole outgoing message. The default factory creates a bean
property parameter source for a generic input (like a Message), and treats a List in a special way: the List is
assumed to contain entities with a field called "id" and these are collected and copied to a field in the
parameter source called "idList".
</xsd:documentation>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.jdbc.SqlParameterSourceFactory" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>

View File

@@ -25,7 +25,7 @@ public class JdbcMessageHandlerParserTests {
private ConfigurableApplicationContext context;
@Test
public void testSimpleInboundChannelAdapter(){
public void testSimpleOutboundChannelAdapter(){
setUp("handlingWithJdbcOperationsJdbcOutboundChannelAdapterTest.xml", getClass());
Message<?> message = MessageBuilder.withPayload("foo").setHeader("business.key", "FOO").build();
channel.send(message);
@@ -35,7 +35,7 @@ public class JdbcMessageHandlerParserTests {
}
@Test
public void testDollarHeaderInboundChannelAdapter(){
public void testDollarHeaderOutboundChannelAdapter(){
setUp("handlingDollarHeaderJdbcOutboundChannelAdapterTest.xml", getClass());
Message<?> message = MessageBuilder.withPayload("foo").build();
channel.send(message);
@@ -45,13 +45,23 @@ public class JdbcMessageHandlerParserTests {
}
@Test
public void testMapPayloadInboundChannelAdapter(){
public void testMapPayloadOutboundChannelAdapter(){
setUp("handlingMapPayloadJdbcOutboundChannelAdapterTest.xml", getClass());
Message<?> message = MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build();
channel.send(message);
Map<String, Object> map = this.jdbcTemplate.queryForMap("SELECT * from FOOS");
assertEquals("Wrong id", message.getHeaders().getId().toString(), map.get("ID"));
assertEquals("Wrong id", "bar", map.get("name"));
assertEquals("Wrong name", "bar", map.get("name"));
}
@Test
public void testParameterSourceOutboundChannelAdapter(){
setUp("handlingParameterSourceJdbcOutboundChannelAdapterTest.xml", getClass());
Message<?> message = MessageBuilder.withPayload("foo").build();
channel.send(message);
Map<String, Object> map = this.jdbcTemplate.queryForMap("SELECT * from FOOS");
assertEquals("Wrong id", message.getHeaders().getId().toString(), map.get("ID"));
assertEquals("Wrong name", "foo", map.get("name"));
}
@After

View File

@@ -1,10 +1,12 @@
package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
@@ -24,18 +26,16 @@ public class JdbcPollingChannelAdapterParserTests {
final long receiveTimeout = 5000;
SimpleJdbcTemplate jdbcTemplate;
MessageChannelTemplate channelTemplate;
ConfigurableApplicationContext appCtx;
private SimpleJdbcTemplate jdbcTemplate;
private MessageChannelTemplate channelTemplate;
private ConfigurableApplicationContext appCtx;
@Test
public void testSimpleInboundChannelAdapter(){
setUp("pollingForMapJdbcInboundChannelAdapterTest.xml", getClass());
this.jdbcTemplate.update("insert into item values(1,2)");
this.jdbcTemplate.update("insert into item values(1,'',2)");
Message<?> message = channelTemplate.receive();
assertNotNull("No message found ", message);
assertTrue("Wrong payload type expected instance of List", message.getPayload() instanceof List<?>);
@@ -45,7 +45,7 @@ public class JdbcPollingChannelAdapterParserTests {
@Test
public void testSimpleInboundChannelAdapterWithUpdate(){
setUp("pollingForMapJdbcInboundChannelAdapterWithUpdateTest.xml", getClass());
this.jdbcTemplate.update("insert into item values(1,2)");
this.jdbcTemplate.update("insert into item values(1,'',2)");
Message<?> message = channelTemplate.receive();
assertNotNull(message);
message = channelTemplate.receive();
@@ -55,11 +55,22 @@ public class JdbcPollingChannelAdapterParserTests {
@Test
public void testExtendedInboundChannelAdapter(){
setUp("pollingWithJdbcOperationsJdbcInboundChannelAdapterTest.xml", getClass());
this.jdbcTemplate.update("insert into item values(1,2)");
this.jdbcTemplate.update("insert into item values(1,'',2)");
Message<?> message = channelTemplate.receive();
assertNotNull(message);
}
@Test
public void testParameterSourceInboundChannelAdapter(){
setUp("pollingWithParameterSourceJdbcInboundChannelAdapterTest.xml", getClass());
this.jdbcTemplate.update("insert into item values(1,'',2)");
Message<?> message = channelTemplate.receive();
assertNotNull(message);
List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT * FROM item WHERE status=1");
assertEquals(1, list.size());
assertEquals("bar", list.get(0).get("NAME"));
}
@After
public void tearDown(){
if(appCtx != null){

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration/jdbc"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:si="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd">
<outbound-channel-adapter query="insert into foos (id, status, name) values (:headers[$id], 0, :payload)"
channel="target" data-source="dataSource" sql-parameter-source-factory="sqlParameterSourceFactory"/>
<beans:import resource="jdbcOutboundChannelAdapterCommonConfig.xml" />
<beans:bean id="sqlParameterSourceFactory" class="org.springframework.integration.jdbc.DefaultSqlParameterSourceFactory">
<beans:property name="staticParameters">
<beans:map><beans:entry key="foo" value="bar"/></beans:map>
</beans:property>
</beans:bean>
</beans:beans>

View File

@@ -1 +1 @@
create table item(id int,status int);
create table item(id int, name varchar(20), status int);

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration/jdbc" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:si="http://www.springframework.org/schema/integration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd">
<inbound-channel-adapter query="select * from item where status=2" channel="target" update="update item set status=1, name=:foo where id in (:idList)"
jdbc-operations="jdbcTemplate" sql-parameter-source-factory="sqlParameterSourceFactory" />
<beans:import resource="jdbcInboundChannelAdapterCommonConfig.xml" />
<beans:bean id="sqlParameterSourceFactory" class="org.springframework.integration.jdbc.DefaultSqlParameterSourceFactory">
<beans:property name="staticParameters">
<beans:map><beans:entry key="foo" value="bar"/></beans:map>
</beans:property>
</beans:bean>
</beans:beans>