仍然在使用连接池后无法对关闭的ResultSet错误进行操作

时间:2014-10-05 01:09:39

标签: java mysql multithreading jdbc c3p0

我有很多线程访问MYSQL数据库,起初我没有使用连接池,所以我遇到了这个错误“你无法对一个封闭的ResultSet进行操作”

我在Google上搜索并发现我应该使用连接池,所以我尝试使用c3p0 API进行实现,但我仍然遇到同样的问题并且没有任何改变。 我应该同步getAllcountries方法还是另一个更好的解决方案。

public class DataSource {

private static DataSource datasource;
private ComboPooledDataSource cpds ; 

private DataSource() throws IOException, SQLException, PropertyVetoException {
    cpds = new ComboPooledDataSource();
    cpds.setDriverClass("com.mysql.jdbc.Driver"); //loads the jdbc driver
    cpds.setJdbcUrl("jdbc:mysql://localhost/question_game");
    cpds.setUser("root");
    cpds.setPassword("");
    cpds.setMaxPoolSize(500);
    }

public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {
    if (datasource == null) {
        datasource = new DataSource();
        return datasource;
    } else {
        return datasource;
    }
}

public  Connection getConnection() throws SQLException {
    return this.cpds.getConnection();
}


public  List<Country> getAllCountries() {
    String query = "SELECT * FROM country order by name ";
    List<Country> list = new ArrayList<Country>();
    Country country = null;
    ResultSet rs = null;
    try {
        try {
            connection = DataSource.getInstance().getConnection();
            } catch (IOException e) {
            e.printStackTrace();
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        statement = connection.createStatement();
        rs = statement.executeQuery(query);
        while (rs.next()) {
              //getting countries
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
    } finally {
        //DbUtil used to check if null 
        DbUtil.close(rs);
        DbUtil.close(statement);
        DbUtil.close(connection);
    }
    return list;

}

2 个答案:

答案 0 :(得分:2)

除了@ stephen-c的观察, 你基本上有两个选择:同步getAllCountries方法,或者使数据库连接本地化为该方法,而不是将它作为类成员。

正如你现在所知,'connection'是一个类成员(可用于所有线程上的所有getAllCountries()调用),因此连接可能被第二个线程覆盖。将它移动到方法中的变量,然后每次调用该方法都有自己的连接。

答案 1 :(得分:0)

我看到一个名为getConnection的方法,我不知道你在哪里调用它。相反,我看到你的getAllCountries方法使用了这样创建的静态DataSource对象:

new DataSource();

  

我在Google上搜索并发现我应该使用连接池,所以我尝试使用c3p0 API进行实现,但我仍然遇到同样的问题并且没有任何变化

是啊......

看起来你只是将你在应用程序中找到的代码剪切并粘贴而没有真正考虑它。显然......你需要理解代码正在做什么并且弄明白如何在你的应用程序中使用