java - 重用PreparedStatement会导致SQLException

标签 java jdbc try-with-resources

尝试使用资源给我以下异常:

java.sql.SQLException: Operation not allowed after ResultSet closed

我的代码:

public Set<Tablet> viewAllTablets(int offset, int noOfRecords) throws OutOfRangeException {
    Set<Tablet> tabletSet = new HashSet<>();
    Tablet tablet = null;

    try(Connection connection = dataSource.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("SELECT SQL_CALC_FOUND_ROWS * FROM tablets limit " + offset + ", " + noOfRecords + ";");
        ResultSet resultSet = preparedStatement.executeQuery();
        ResultSet resultSet1 = preparedStatement.executeQuery("SELECT FOUND_ROWS()");){

        while (resultSet.next()){
            tablet = new Tablet();
            tablet.setTabletId(resultSet.getInt("idTablet"));
            tablet.setName(resultSet.getString("name"));
            tablet.setNeedRecepie(resultSet.getBoolean("need_recipe"));
            tablet.setPrice(resultSet.getDouble("price"));
            tablet.setTypeId(resultSet.getInt("type_id"));
            tablet.setDescription(resultSet.getString("description"));
            tablet.setTabletType(TypeFactory.getType(tablet.getTypeId()));
            tablet.setWeight(resultSet.getDouble("weight_of_pack"));
            tablet.setPillsCount(resultSet.getInt("pills_count"));
            tabletSet.add(tablet);
        }
        if(resultSet1.next())
            this.noOfRecords = resultSet1.getInt(1);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return tabletSet;
}

最佳答案

PreparedStatement 上执行第二个查询会隐式关闭前一个查询的 ResultSet。来自 Statement :

By default, only one ResultSet object per Statement object can be open at the same time.

使用两个不同的语句,沿着这些思路(注意如何检索 resultSet1),尽管我当然不知道您的 FOUND_ROWS 函数的要求是什么:

try (
    Connection connection = dataSource.getConnection();
    PreparedStatement preparedStatement = connection.prepareStatement("SELECT SQL_CALC_FOUND_ROWS * FROM tablets limit " + offset + ", " + noOfRecords + ";");
    ResultSet resultSet = preparedStatement.executeQuery();
    ResultSet resultSet1 = connection.createStatement().executeQuery("SELECT FOUND_ROWS()"); // ****
    ) {
    while (resultSet.next()) {
        tablet = new Tablet();
        tablet.setTabletId(resultSet.getInt("idTablet"));
        tablet.setName(resultSet.getString("name"));
        tablet.setNeedRecepie(resultSet.getBoolean("need_recipe"));
        tablet.setPrice(resultSet.getDouble("price"));
        tablet.setTypeId(resultSet.getInt("type_id"));
        tablet.setDescription(resultSet.getString("description"));
        tablet.setTabletType(TypeFactory.getType(tablet.getTypeId()));
        tablet.setWeight(resultSet.getDouble("weight_of_pack"));
        tablet.setPillsCount(resultSet.getInt("pills_count"));
        tabletSet.add(tablet);
    }
    if (resultSet1.next())
        this.noOfRecords = resultSet1.getInt(1);
} catch (SQLException e) {
    e.printStackTrace();
}
<小时/>

另外:不要在 PreparedStatement 上使用 StatementexecuteQuery(String)。它确实不应该在那里,这是 java.sql 包设计中的一个缺陷。事实上,Statement#executeQuery 的文档说:

Note:This method cannot be called on a PreparedStatement or CallableStatement.

关于java - 重用PreparedStatement会导致SQLException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38389454/

相关文章:

java - 正确查询的 MysqlSyntaxError

java - 我应该如何使用 `try-with-resources` 中的 IOException 嵌套在 header 中带有`throws IOException`的方法中?

Java代码-多边形的面积

java - 给出两个项目之间值(value)的相对差异

java - 一个Web服务可以调用同一应用服务器中的另一个Web服务吗

java - 无法使用类加载器建立连接

java - 格式化 hql 查询

apache-spark - 从JDBC创建spark数据帧时如何指定sql方言?

java - Java中如何保证Closeable接口(interface)的close()方法的幂等性?

java - Try-With-Resources 中的多个资源 - 里面的语句