使用 addBatch 和 executeBatch 时是否必须使用相同的 prepareCall?为什么?
Do I have to use the same prepareCall when using addBatch & executeBatch? Why?
我是 JDBC 的新手,正在学习如何使用批处理。在浪费了很多时间试图找出为什么我的 JavaScript 和 SQL 存储过程的组合不起作用之后,我想我知道你必须在使用 prepareCall
时使用 addBatch
和 executeBatch
。这是真的?如果是,为什么?
为了举例说明,这里有一些示例输入:
var vals = [["value1_1","value2_1","value3","value4","value5","value6_1"],
["value1_2","value2_2","value3","value4","value5","value6_2"]]
下面的循环按预期工作。注意我在进入循环之前prepareCall
.
params = Array(vals.length).fill("?")
pstmt = conn.prepareCall("{call "+storedProcedure+"("+params+")}");
for (var i = 0; i < vals.length; i++) { // for each array
for (var j = 0; j < vals[i].length; j++) { // for each value within each array
// set the string
pstmt.setString(j+1, vals[i][j]);
}
pstmt.addBatch();
}
try {
pstmt.executeBatch();
} catch (err) {
//my err msg code
pstmt.close();
conn.close();
}
现在,有时我的记录具有不同数量的参数,所以我想我可以将 prepareCall
移动到第一个循环中,这样我就可以根据需要为每个输入数组更改参数数量.
for (var i = 0; i < vals.length; i++) { // for each array
// moved prepareCall here
params = Array(vals.length).fill("?")
pstmt = conn.prepareCall("{call "+storedProcedure+"("+params+")}");
for (var j = 0; j < vals[i].length; j++) { // for each value within each array
// set the string
pstmt.setString(j+1, vals[i][j]);
}
pstmt.addBatch();
}
try {
pstmt.executeBatch();
} catch (err) {
//my err msg code
pstmt.close();
conn.close();
}
对于第二个循环,我没有从 Javascript 中得到任何错误,但是我从我的存储过程中得到一个外部约束错误。我的存储过程制作了一组 CALL
s 以根据最后一个参数的值创建记录。我知道我得到的错误是告诉我 FK
之一不存在。仅当调用了错误的 CALL
集或调用了正确的 CALL
集但其中一个 CALL
失败时,才会发生这种情况。我确定这都不是问题,因为第一个循环按预期工作。
因此,我有兴趣了解为什么在 executeBatch
时必须使用一个 prepareCall
?确认一下,当我用不同数量的参数调用不同的存储过程时,我必须使用完全独立的 prepareCall
s?
我认为这不重要,但为了更好的衡量:我正在使用 MySQL 5.7.
方法 prepareCall
returns 为您传递给 prepareCall
的特定语句编译的 CallableStatement
对象。当您调用 addBatch
时,参数集将添加到 CallableStatement
的特定实例中。如果你再次执行 prepareCall
,你会得到一个 不同的 CallableStatement
句柄,有自己的批次。
因此,在外循环每次迭代的第二段代码中,您创建了一个 new CallableStatement
,丢失了先前的可调用语句及其批处理 (在您的代码中以及可能在您的 DBMS 中创建内存泄漏)。因此,当您调用 executeBatch
时,您只会执行您准备的 last 语句,并且只有一组参数值。
如果需要执行不同的语句文本,则需要按顺序准备和执行,不能使用batch(*)。
* - 如果多组参数使用相同的语句文本,您可以使用批处理,但如果不同语句文本之间存在顺序依赖性,这可能会变得棘手
我是 JDBC 的新手,正在学习如何使用批处理。在浪费了很多时间试图找出为什么我的 JavaScript 和 SQL 存储过程的组合不起作用之后,我想我知道你必须在使用 prepareCall
时使用 addBatch
和 executeBatch
。这是真的?如果是,为什么?
为了举例说明,这里有一些示例输入:
var vals = [["value1_1","value2_1","value3","value4","value5","value6_1"],
["value1_2","value2_2","value3","value4","value5","value6_2"]]
下面的循环按预期工作。注意我在进入循环之前prepareCall
.
params = Array(vals.length).fill("?")
pstmt = conn.prepareCall("{call "+storedProcedure+"("+params+")}");
for (var i = 0; i < vals.length; i++) { // for each array
for (var j = 0; j < vals[i].length; j++) { // for each value within each array
// set the string
pstmt.setString(j+1, vals[i][j]);
}
pstmt.addBatch();
}
try {
pstmt.executeBatch();
} catch (err) {
//my err msg code
pstmt.close();
conn.close();
}
现在,有时我的记录具有不同数量的参数,所以我想我可以将 prepareCall
移动到第一个循环中,这样我就可以根据需要为每个输入数组更改参数数量.
for (var i = 0; i < vals.length; i++) { // for each array
// moved prepareCall here
params = Array(vals.length).fill("?")
pstmt = conn.prepareCall("{call "+storedProcedure+"("+params+")}");
for (var j = 0; j < vals[i].length; j++) { // for each value within each array
// set the string
pstmt.setString(j+1, vals[i][j]);
}
pstmt.addBatch();
}
try {
pstmt.executeBatch();
} catch (err) {
//my err msg code
pstmt.close();
conn.close();
}
对于第二个循环,我没有从 Javascript 中得到任何错误,但是我从我的存储过程中得到一个外部约束错误。我的存储过程制作了一组 CALL
s 以根据最后一个参数的值创建记录。我知道我得到的错误是告诉我 FK
之一不存在。仅当调用了错误的 CALL
集或调用了正确的 CALL
集但其中一个 CALL
失败时,才会发生这种情况。我确定这都不是问题,因为第一个循环按预期工作。
因此,我有兴趣了解为什么在 executeBatch
时必须使用一个 prepareCall
?确认一下,当我用不同数量的参数调用不同的存储过程时,我必须使用完全独立的 prepareCall
s?
我认为这不重要,但为了更好的衡量:我正在使用 MySQL 5.7.
方法 prepareCall
returns 为您传递给 prepareCall
的特定语句编译的 CallableStatement
对象。当您调用 addBatch
时,参数集将添加到 CallableStatement
的特定实例中。如果你再次执行 prepareCall
,你会得到一个 不同的 CallableStatement
句柄,有自己的批次。
因此,在外循环每次迭代的第二段代码中,您创建了一个 new CallableStatement
,丢失了先前的可调用语句及其批处理 (在您的代码中以及可能在您的 DBMS 中创建内存泄漏)。因此,当您调用 executeBatch
时,您只会执行您准备的 last 语句,并且只有一组参数值。
如果需要执行不同的语句文本,则需要按顺序准备和执行,不能使用batch(*)。
* - 如果多组参数使用相同的语句文本,您可以使用批处理,但如果不同语句文本之间存在顺序依赖性,这可能会变得棘手