连接池:为什么方法结束之后,连接池中所有链接都结束了???

1.问题:
我写了一个DBUtil 操作数据库基类,使用的时 druid连接池。


public class DBUtil {

    //省略其它代码

    //连接数据库的对象
    private Connection con ;
    //建立操作指令对象
    private PreparedStatement ps;
    //操作结果的对象
    private ResultSet rs;


    //创建 数据库对象,建立连接
    public void getCon() {
            try {
                // 连接池 操作
                Properties properties = new Properties();
                properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("database.properties"));
                DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
                con = dataSource.getConnection();

            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
    }

    //查
    public ResultSet query(String sql, Object[] obj){
        getCon();
        try {
            ps = con.prepareStatement(sql);
            for(int i = 0; i<obj.length; i++){
                 ps.setObject(i+1, obj[i]);
            }
            rs = ps.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }

    public void close(){
        try {
            if(con != null){
                con.close();
            }
            if(ps != null){
                ps.close();
            }
            if(rs != null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

配置文件中:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/library?allowMultiQueries=true
username=root
password=123
minIdle=10
maxIdle=50
initialSize=3
maxActive=100
maxWait=100
removeAbandonedTimeout=180
removeAbandoned=true

当我写一个Test()方法测试的时候,发现连接池就会多次创建,并且当方法结束之后,连接池中又没有连接数了

    @Test
    public void show(){
        Object [] Object = {};
        DBUtil dbUtil = new DBUtil();
        long startTime=System.currentTimeMillis();   //获取开始时间
        ResultSet rs = null;
        for (int i = 0; i < 2; i++) {
            rs = dbUtil.query("select id from logtable", Object);
             dbUtil.close();
        }

        long endTime=System.currentTimeMillis(); //获取结束时间
        System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
    }

详细如图:

图片说明

图片说明

图片说明

图片说明

图片说明

实在不清楚怎么回事,还请各位老哥 解惑! 谢谢


上一个问题,有了一点眉目,现在我又有些疑问了。

新的问题

现在又有一个问题
我把查询方法抽成了一个公共方法 ** query() 方法** :如

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)

图片说明

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

那我就有疑问了,怎么才能抽成一个公共方法,当去调用这个公共方法时,不报这个异常,**这个怎么解决啊**,各位老哥

你的DBUtil getCon() 方法有问题:DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

这里的dataSource是数据源,不能重复生成的,只需要一个。把dataSource放到类的成员变量,使用static块获取dataSource

参考:https://www.cnblogs.com/yulinfeng/p/5986395.html

getCon方法中:
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
因此每次调用getCon都会新建立一个连接池。

test方法执行完,jvm关闭,资源释放。

你这直接都把数据库关闭了,getCon()方法每次查询都要调用,不能创建一次,操作完成后再关闭数据库连接啊

test 方法结束了,Java 进程也就结束了,那么相应的数据库连接也就自动断开了。
如果想对比测试的话,test 后面 sleep 一会儿,看看数据库端是不是还有连接。

应该把dataSource对象设置为类的静态变量,然后在初始化时dataSource使用一个单独方法初始化

public static DataSource synchronized getDataSource(){
    if(dataSource==null){
        //初始化代码
    }
    return dataSource;
}