Ste*_*ume 95 java jdbc prepared-statement
如果将PreparedStatement与没有任何池的单个公共连接一起使用,我是否可以为每个dml/sql操作重新创建一个实例来保证预处理语句的强大功能?
我的意思是:
for (int i=0; i<1000; i++) {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, someValue);
preparedStatement.executeQuery();
preparedStatement.close();
}
Run Code Online (Sandbox Code Playgroud)
代替:
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i=0; i<1000; i++) {
preparedStatement.clearParameters();
preparedStatement.setObject(1, someValue);
preparedStatement.executeQuery();
}
preparedStatement.close();
Run Code Online (Sandbox Code Playgroud)
我的问题是因为我想把这段代码放到多线程环境中,你能给我一些建议吗?谢谢
Bal*_*usC 140
第二种方式更有效,但更好的方法是批量执行它们:
public void executeBatch(List<Entity> entities) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL);
) {
for (Entity entity : entities) {
statement.setObject(1, entity.getSomeProperty());
// ...
statement.addBatch();
}
statement.executeBatch();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,您依赖于JDBC驱动程序实现,您可以一次执行多少批次.例如,您可能希望每1000批次执行它们:
public void executeBatch(List<Entity> entities) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL);
) {
int i = 0;
for (Entity entity : entities) {
statement.setObject(1, entity.getSomeProperty());
// ...
statement.addBatch();
i++;
if (i % 1000 == 0 || i == entities.size()) {
statement.executeBatch(); // Execute every 1000 items.
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于多线程环境,如果使用try-with-resources语句按照常规JDBC惯用法获取并关闭同一方法块内最短可能范围内的连接和语句,则无需担心这一点,如下所示:片段以上.
如果这些批处理是事务性的,那么您希望关闭连接的自动提交,并且只在所有批处理完成时提交事务.否则,当第一批批次成功而后者不成功时,可能会导致脏数据库.
public void executeBatch(List<Entity> entities) throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SQL)) {
// ...
try {
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Thi*_*ilo 13
代码中的循环只是一个过于简化的例子,对吧?
最好只创建一次PreparedStatement,然后在循环中重复使用它.
在不可能的情况下(因为它使程序流程太复杂化),使用PreparedStatement仍然是有益的,即使你只使用它一次,因为工作的服务器端(解析SQL和缓存执行计划),仍将减少.
为了解决您想要重用Java端PreparedStatement的情况,一些JDBC驱动程序(例如Oracle)具有缓存功能:如果在同一连接上为同一SQL创建PreparedStatement,它将为您提供相同的(缓存)实例.
关于多线程:我不认为JDBC连接可以在多个线程之间共享(即多个线程同时使用).每个线程都应该从池中获取自己的连接,使用它,然后再将它返回池中.
| 归档时间: |
|
| 查看次数: |
96727 次 |
| 最近记录: |