kev*_*rpe 22 java sql prepared-statement
想象一下,我有100个SELECT查询,它们因一个输入而不同.PreparedStatement可用于该值.
我在Web上看到的所有文档都是批量插入/更新/删除.我从未见过用于select语句的批处理.
可以这样做吗?如果是这样,请在下面的示例代码中帮助我.
我想这可以使用"IN"子句来完成,但我更喜欢使用批处理的select语句.
示例代码:
public void run(Connection db_conn, List value_list) {
String sql = "SELECT * FROM DATA_TABLE WHERE ATTR = ?";
PreparedStatement pstmt = db_conn.prepareStatement(sql);
for (String value: value_list) {
pstmt.clearParameters();
pstmt.setObject(1, value);
pstmt.addBatch();
}
// What do I call here?
int[] result_array = pstmt.executeBatch()
while (pstmt.getMoreResults()) {
ResultSet result_set = pstmt.getResultSet();
// do work here
}
}
我想这也可能是依赖于驱动程序的行为.我正在使用他们的JDBC驱动程序编写针对IBM AS/400 DB2数据库的查询.
JDBC不允许创建批处理SELECT查询,我认为这是一个令人沮丧的限制,特别是因为准备好的语句不允许您指定可变数量的参数(如IN (...)子句)。
JavaRanch的文章FJ链接到建议通过创建一系列固定大小的查询并结合其结果来模拟批处理,这对我来说似乎是繁琐且次优的解决方案。您必须立即手动构造和处理多个查询,并多次访问数据库。如果为手动定义的批次选择的数字很差,那么您可能会为了回答一个简单的查询而多次访问数据库。
取而代之的是,我开始PreparedStatement使用需要的字段数量来动态构造对象。这确实意味着PreparedStatement,与手动批处理相比,可能创建的s 数量更多,但是我们限制了访问数据库的频率并简化了实现,我认为这两者都是更重要的问题。
/**
* Use this method to create batch-able queries, e.g:
* "SELECT * FROM t WHERE x IN (?, ?, ?, ?)"
* Can be built as:
* "SELECT * FROM t where x IN ("+getLineOfQs(4)+")"
*/
public static String getLineOfQs(int num) {
// Joiner and Iterables from the Guava library
return Joiner.on(", ").join(Iterables.limit(Iterables.cycle("?"), num));
}
/**
* Gets the set of IDs associated with a given list of words
*/
public Set<Integer> find(Connection conn, List<String> words)
throws SQLException {
Set<Integer> result = new HashSet<>();
try(PreparedStatement ps = conn.prepareStatement(
"SELECT id FROM my_table WHERE word IN ("+
getLineOfQs(words.size())+")")) {
for(int i = 0; i < words.size(); i++) {
ps.setString(i+1, words.get(i));
}
try (ResultSet rs = ps.executeQuery()) {
while(rs.next()) {
result.add(rs.getInt("id"));
}
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
这对于代码来说并不太麻烦,为您提供了使用的安全性PreparedStatement,并避免了不必要的数据库访问。