spring 批次中子句中的准备语句

preparedstatemnt in clause in spring batch

美好的一天,

在spring批次reader中,通常我会在reader里面放一个sql。 例如。

<bean id="zReader" class="ibs.batch.job.reader.ZTableReader" scope="step">
    <property name="dataSource" ref="dataSource" />
    <property name="sql"
        value="SELECT ZP.EMPLOYEEOLDIC, ZP.EMPLOYEENEWIC, ZP.EMPLOYEENAME, ZP.AMOUNT, ZP.ZAKATCODE
                      FROM S.ZPAYMENT ZP
                      WHERE ZP.DEDUCTIONMONTH = ? AND ZP.COMPANYREGNO = ?
                      AND ZP.MODIFIEDBY IS NULL " />
    <property name="preparedStatementSetter" ref="zReader" />
    <property name="rowMapper">
        <bean class="ibs.batch.job.reader.mapper.ZPaymentReaderTableMapper" />
    </property>
    <property name="saveState" value="false" />
</bean>

然后,在我们的 reader java 文件中,我们将设置参数

@Override
public void setValues(PreparedStatement ps) throws SQLException {
    ps.setString( 1, employerName );
    ps.setString( 2, monthOfContribution );
}

现在我想将查询更改为

SELECT ZP.EMPLOYEEOLDIC, ZP.EMPLOYEENEWIC, ZP.EMPLOYEENAME, ZP.AMOUNT, ZP.ZAKATCODE
                        FROM S.ZPAYMENT ZP
                        WHERE ZP.UserId in (?)

并在 reader java 文件中,

String userIds = "'1871','1872'";
ps.setString( 1, userIds );

但我会继续打SqlExceptionSqlState = 22018

这在 spring 批次中可行吗?

您不能用一个占位符代表多个值。占位符不仅仅是您稍后设置的参数值被复制粘贴的地方。换句话说,将 ? 替换为 '1871','1872' 是否有效这一事实是无关紧要的,因为那不是 jdbc 驱动程序所做的。

实际上每个单独的值都需要一个占位符,这意味着如果要发送不同数量的值,则不能使用单个静态 SQL 字符串。你必须想出另一种策略(比如,在所需值之前插入一个单独的临时 table 然后 select 从插入语句中的那个临时 table ,包装一个类 在另一个中修复了 SQL 语句,然后再委托给它,等等)

这是 in 查询的问题,如果您已经知道 in 提供的参数数量,那么可以像这样使用它

WHERE ZP.UserId in (?,?)

and p.setString(1,'1871') p.setString(2,'1871')

否则,通过在 in 中附加字符串并触发查询来构造一个 sql 查询,据我所知,对于 in 查询和 preparedstatement 这个问题没有合适的解决方案。

我发现还有一个更好的办法。

也就是不把sql查询写在xml文件里,写在ZTableReaderjava文件里的beforeStep()方法里。在这里,我可以构造一个 StringStringBuilder 来构建我的 sql 灵活查询。然后用户 setSql() 设置 Sql 查询。

示例代码:

String sql = "Select * from tableA where .....";

setSql(sql); 

然后将 sql 的虚拟值放入 xml 文件中,例如:

<property name="sql" value="dummy" />

当到达 ZTableReaderbeforeStep() 时,"dummy" 值将被我定义的 sql 覆盖。