我正在实现一种模式来绕过JDBC限制。对于预准备语句,JDBC将占位符数限制为2100.为了解决这个问题,我使用包含2100+值的xml字符串,并使用函数tf_splitxml在SQL Server端解析它。我正在为使用预准备语句的~4个Java方法执行此操作。
这个tf_splitxml只构造一个包含所有值的列“token”。所以xml字符串为:
'<node><value>1</value><value>2</value></node>'
将转换为包含两行的列,值为1和2。
此模式似乎适用于select语句,但更新语句失败。这是一般模式:
declare @xml xml; set @xml = ?; --Replaced with xml string in PreparedStatement
update tableX
...
where ids in (select token from tf_splitxml(@xml));
它告诉我将nvarchar值转换为数据类型int时转换失败。 [对于上面的xml字符串]。奇怪的是,如果我提取由预准备语句设置的查询,我可以在SQL Server中完美地运行它!
我的想法:
我尝试过的事情:
我创建了一个表,可以保存从tf_splitxml生成的标记。对于失败的方法,在JDBC抛出错误之前永远不会调用tf_splitxml。
在Java方面,我使用的是ps.setString(index,convertToXML(idsArray))。这适用于前3种方法,即使我的@xml不是字符串(它被声明为xml变量)。我尝试将其切换到SQLXML对象,但无济于事。我仍然可以使用相同的3/4方法。
我可以直接在SQL Server编辑器中直接运行所有准备好的查询。
我最诚挚的感谢! :)
答案 0 :(得分:1)
该代码看起来很疯狂,请查看我的ChunkWorkTemplate。这是一个简单的例子:
public void delete(final List<Integer> employeeIds) {
new ChunkWorkTemplate<Integer>(50, employeeIds) {
protected void executeOnChunk(List<Integer> chunk) {
Session session = getSession();
Query query = session.createSQLQuery("delete from Employee where employeeId in (:employeeIds)");
query.setParameterList("employeeIds", chunk);
query.executeUpdate();
}
}.execute();
}
请注意,模板的第一个参数是块大小,您可以将其设置为您喜欢的任何内容。基本上,它将填充输入集合并以块的形式执行正文。因此,在上面的示例中,如果您有207个员工ID,块大小为50,则您将拥有5个块(50 + 50 + 50 + 50 + 7)。我这样写是为了解决你所面临的确切问题。希望这会有所帮助。