JDBC 如何抽成一个公共查询方法,并正确释放资源 close() 10C

1.描述问题

将查询数据库操作,抽成一个公共方法,如下:

public class DBPoolConnection {
    private static ResultSet resultSet;
    private static DruidPooledConnection conn = null;
    private PreparedStatement ps = null;
    private static DBPoolConnection dbPoolConnection = null;
    private static DruidDataSource druidDataSource = null;

    static {
        Properties properties = new Properties();
        try {
            properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("database.properties"));
            druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);    //DruidDataSrouce工厂模式

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 数据库连接池单例
     * @return
     */
    public static synchronized DBPoolConnection getInstance(){
        if (null == dbPoolConnection){
            dbPoolConnection = new DBPoolConnection();
        }
        return dbPoolConnection;
    }

    /**
     * 返回druid数据库连接
     * @return
     * @throws SQLException
     */
    public DruidPooledConnection getConnection() throws SQLException {
        return druidDataSource.getConnection();
    }

    /**
     * @Description 查询的公共方法
     */
    public ResultSet query(String sql,Object [] objects){
        try {
            DBPoolConnection dbPoolConnection = DBPoolConnection.getInstance();
            conn = dbPoolConnection.getConnection();
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < objects.length; i++) {
                ps.setObject(i,objects[i]);
            }
            resultSet = ps.executeQuery();
        } catch (SQLException e) {
            System.out.println("有异常");
            e.printStackTrace();
        }finally {
            try {
                if (null != ps) {
                    ps.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return resultSet;
    }

}

当我写一个测试方法,如:

    @Test
    public void Test(){
        Object [] Object = {};
        DBPoolConnection dbPoolConnection = new DBPoolConnection();
        ResultSet rs = null;
        for (int i = 0; i < 2; i++) {
            rs = dbPoolConnection.query("select id from logtable", Object);
        }
        String id = "";
        if (null != rs) {
            try {
                if (rs.next()) {
                    rs.previous();
                    while (rs.next()){
                        id = rs.getString("id");
                    }
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                try {
                    if (null != rs) {
                        rs.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            }
        }
        System.out.println("-------------获取数据:"+id);
    }

执行后就提示:

java.sql.SQLException: Operation not allowed after ResultSet closed
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
    at com.mysql.jdbc.ResultSet.checkClosed(ResultSet.java:666)
    at com.mysql.jdbc.ResultSet.next(ResultSet.java:7274)

图片说明

百度了一下,这个是因为提前关闭了连接。

问:

怎么才能抽成一个公共方法,当在其它类中去调用 query() 这个公共方法时,不报这个异常... 并正确释放资源呢

2个回答

这个看起来是close顺序有问题把,

把这段代码先注掉试一下

try {
                if (null != ps) {
                    ps.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

写一个类,持有resultSet,conn,ps三个对象
query方法返回这个类的实例
这个类中定义方法close 关闭三个对象

weixin_39606236
꧁gaoKuo꧂ 回复沐风Cc: 补充回答了
一年多之前 回复
mufeng633
沐风Cc 我注释了,是不报异常了,也能获取到值。但是如果像你说的:我改了之后,这个资源关闭 close()方法应该在什么时候进行关闭呢?如果 是在公共方法 query()方法中,那么就会报这个异常啊,如果我在测试Test()方法中关闭。因为没有 conn 对象,那么 conn.close(); 就没办法执行啊。 还请解惑
一年多之前 回复

不建议返回resultSet来操作,操作它还要处理相关的异常。最终只是要返回的数据,query直接提取数据然后返回你封装的数据就好了,也可以返回Map比较方便。

qq_27718453
庄粟 回复沐风Cc: 百度下很多:https://chen498402552-163-com.iteye.com/blog/786289
一年多之前 回复
mufeng633
沐风Cc 得到ResultSet对象,因为获取里面的值数量是不固定的,这里我就获取了一个 id, 如果有多个呢? 我不知道怎么封装这个query()方法并返回map数据,有没有资料参考啊
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐