addBatch()和executeBatch()线程安全吗?

pal*_*rom 5 java jdbc thread-safety

我可以从一个线程调用executeBacth而另一个继续在同一个Statement(或PreparedStatement)对象上调用addBatch()吗?

更新:有没有人对此问题有所了解?因为我的结果不正确.并非所有添加到批处理中的更新都会执行.

Bal*_*usC 19

我会退后一步,深深地重新考虑设计.为什么你想在两个线程之间共享相同的Statement(因而也是隐含的Connection)呢?

正常的JDBC的做法是,你应该获得和关闭Connection,StatementResultSet最短的可能范围.也就是说,在同一个方法块内.这是一个基本的例子:

public void update(List<Item> items) throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    try {
        connection = database.getConnection();
        statement = connection.prepareStatement(sql);
        for (Item item : items) {
            statement.setObject(1, item.getSomething());
            statement.addBatch();
        }
        statement.executeBatch();
    } finally {
        if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
        if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您只想提高连接性能,那么请使用连接池.例如C3P0.但肯定不是线程之间共享昂贵的DB资源!这样您也不必担心线程安全.这是一个实现细节.

哦,如果还不清楚:你不会通过在多个线程之间共享相同的语句和连接来提高数据库性能.更糟糕的是,它只会减速,而且你会遇到Java和数据库方面的线程安全问题.

  • 考虑放置一个工作队列,50个线程添加行更新,1个消耗线程拾取发出`addBatch()`和`executeBatch()`调用的更新. (3认同)

jar*_*bjo 6

是.根据JDBC规范,所有JDBC驱动程序实现必须是线程安全的:

符合JDBC 3.0 API,第A.1.6节


如果我理解你对BalusC的响应的正确评论,你将从一个Statement迭代ResultSet并同时在一个单独的线程中与其他PreparedStatements一起操作以更新其他行.这不一定必须工作(同样它取决于JDBC驱动程序,但与线程安全性没有直接关系).我不确定最新版本,但较旧的Oracle JDBC驱动程序确实例如不支持多个语句,当然没有正确地失败,但是如您所描述的那样产生了意想不到的结果.如果我没记错的话,在迭代第一个语句的结果集时在连接上创建第二个语句将导致第一个语句被静默关闭,第一个结果集只返回已经从数据库中提取的行,尽管更多的行本来可以的.您的实现听起来很相似,并且可能与其他数据库一样显示类似行为.