更新jdbc:inbound-channel-adapter从DB读取记录后的时间戳

时间:2017-01-09 08:07:48

标签: spring spring-integration

我正在使用Spring集成" int-jdbc:inbound-channel-adapter"从数据库中获取记录。但是在我获取记录后,我还需要更新2列        1)状态栏        2)时间戳列

更新状态列不是问题,因为我可以在xml片段下面使用

<int-jdbc:inbound-channel-adapter query="select * from item where status=2"
    channel="target" data-source="dataSource"
    update="update item set status=10 where id in (:id)" />

但是,当我尝试更新时间戳时,它无法正常工作

    <int-jdbc:inbound-channel-adapter query="select * from item where status=2"
        channel="target" data-source="dataSource"
        update="update item set status=10,timestamp=:timestamp where id in (:id)" 
         update-sql-parameter-source-actory="timestampUpdaterSqlParameterSourceFactory">
     <int-jdbc:inbound-channel-adapter>


    <bean id="timestampUpdaterSqlParameterSourceFactory"
          class="org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory"  >
        <property name="parameterExpressions">
            <map>
                <entry key="timestamp" value="@now"/>
            </map>
        </property>
    </bean>

<bean id="now" scope="prototype" class="java.sql.Timestamp">
    <constructor-arg value="#{ T(java.lang.System).currentTimeMillis()}" />
</bean>

我们可以使用DB级方法为oracle设置sysdate的时间,但我并不热衷于在代码中使用特定于DB的方法进行测试(H2 DB用于测试)

非常感谢任何帮助

由于

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,问题是:timestamp表达式被评估为Collection Projection,请检查code here。 所以我的原始查询是这样的

update table set status = 1, published_at = :now where id_event in (:id)

解析之后是这样的

update table set status = 1, published_at = ?, ?, ? where id_event in (?, ?, ?)

?的数量与select语句的结果数相同。因此,如果结果不止一个,则会出现Bad Grammar异常。

我使用spring-integration-java-dsl

制作了一个不太好的解决方案(侵入性)
  protected void addNotCollectionProjectionExpression(
      ExpressionEvaluatingSqlParameterSourceFactory factory,
      String key, String expression) {
    try {
      Field parameterExpressionsField = factory.getClass().getDeclaredField("parameterExpressions");
      parameterExpressionsField.setAccessible(true);
      Map<String, Expression[]> parameterExpressions = (Map<String, Expression[]>) parameterExpressionsField
          .get(factory);

      Field parserField = factory.getClass().getDeclaredField("PARSER");
      parserField.setAccessible(true);

      ExpressionParser parser = (ExpressionParser) parserField.get(factory);

      Expression compiledExpression = parser.parseExpression(expression);
      Expression[] expressions = new Expression[]{
          compiledExpression,
          compiledExpression
      };
      parameterExpressions.put(key, expressions);
    } catch (NoSuchFieldException | IllegalAccessException e) {
      logger.error("Field parameterExpressions | PARSER can not be obtained", e);
    }
  }
 ....
//how to use it
ExpressionEvaluatingSqlParameterSourceFactory factory =
        new ExpressionEvaluatingSqlParameterSourceFactory();
    addNotCollectionProjectionExpression(factory, "now",
        "T(com.example.MyClass).staticMethod()");
    return factory;

你可以注意到我在数组的两个元素中使用相同的表达式避免使用Collection Projection。