我有一个JDBC连接到Oracle RDBMS。
我需要调用一个存储过程(将其命名为foo),该存储过程返回一个数字。
如果我自己执行每条语句,效果很好。
for (int i = 0; i < 10;i ++)
{
CallableStatement cst = con.prepareCall ("{? = foo (" + i + ")}");
cst.registerOutParameter (1, Types.INTEGER);
cst.execute ();
}
现在,我喜欢使用批处理来提高性能。那就是我的方法。
Statement st = con.createStatement ();
for (int i = 0; i < 10;i ++)
{
st.addBatch ("{? = foo (" + i + ")}");
}
st.executeBatch ();
那行不通。
错误告诉我,并非每个变量都被分配。认为这是因为没有返回值的注册,就像上面的工作示例一样。
如果我将语句设置为
{foo (" + i + ")}
删除返回值,然后我得到未定义过程的错误。
在批处理中如何处理具有返回值的存储过程?
答案 0 :(得分:1)
JDBC批处理需要相同的准备语句和一堆绑定变量。
您通过为每个"{? = foo (" + i + ")}"
生成的动态语句i
违反了此规定。
您必须使用带有两个绑定变量"{? = foo (?)}"
不幸的是,这导致了异常
捕获:java.sql.SQLException:不允许操作:无法对带有out或inout参数的存储过程进行批处理
因为不可能从批处理语句返回结果函数调用的集合。
幸运的是,有一个非常简单的替代解决方案。您可以使用prepareStatement模拟批处理 (即,您将往返次数限制为数据库服务器)
def stmt = con.prepareStatement("select foo(rownum) foo from dual connect by level <= 10")
将获取站点设置为与批量大小相同,您将获得相应的行为。