Java连接池-垃圾收集或调用关闭()?

Java连接池-垃圾收集或调用关闭()?,java,connection-pooling,Java,Connection Pooling,我担心的是,我在理解Java中的连接池时遇到了一个根本问题 我正在使用IDBCataSource作为连接池。 在我的应用程序的入口点,我实例化了一个BasicDataSource,例如setMaxActive=50。然后将该数据源的实例传递到各种DAO中,这些DAO由一些业务逻辑使用 每个DAO都调用getConnection,但没有调用单个close。我的假设是,在不使用DAO之后,垃圾收集器会关闭连接 我的问题是,我一直在运行的连接,即代码等待一个可用的连接 现在让我们假设我将在每个数据库操

我担心的是,我在理解Java中的连接池时遇到了一个根本问题

我正在使用IDBCataSource作为连接池。 在我的应用程序的入口点,我实例化了一个BasicDataSource,例如setMaxActive=50。然后将该数据源的实例传递到各种DAO中,这些DAO由一些业务逻辑使用

每个DAO都调用getConnection,但没有调用单个close。我的假设是,在不使用DAO之后,垃圾收集器会关闭连接

我的问题是,我一直在运行的连接,即代码等待一个可用的连接

现在让我们假设我将在每个数据库操作的末尾添加一个close调用。抛出异常时会发生什么。我必须捕获DAO中的每个异常,确保关闭连接,然后重新抛出发生的异常

示例-当前方法:

public class MyDAO {
     private Connection con;

     public MyDAO (DataSource ds) {
          con = ds.getConnection();     
     }     

     public MyReturnClass execSomeQuery() throws SQLException {
          String sql = String.format("SELECT * FROM foo");
          PreparedStatement ps = con.prepareStatement(sql);
          ResultSet rs = ps.executeQuery();

          while (rs.next()) {
               …     
               ...
          }          

          return result;
     }
}


public class MyAppLogic() {
     DataSource ds; 

     public MyAppLogic(DataSource ds) {
          this.ds = ds;
     }

     public void doSomeStuff() {
          MyDAO myDAO = MyDAO(ds);
          myDAO.execSomeQuery();
     }
}

您需要关闭连接,以便它们返回到连接池中。GC不会呼叫关闭您的连接

您需要关闭连接,以便它们返回到连接池中。GC不会呼叫关闭您的连接

您可以创建一个包装器或父类来管理连接,这样就不必在每个方法中复制逻辑。这里有一个示例说明,我实际上并没有编译或测试它

public interface DAOClass {
    public void execSomeQuery() throws SQLException;
}

public class MyDAOWrapper {
    private DAOClass dao;
    private DataSource ds;

    public MyDAOWrapper(DataSource ds, DAOClass dao) {
        this.dao = dao;
        this.ds = ds;
    }

    public void exec() throws SQLException {
        Connection con = ds.getConnection();
        try {
            dao.execSomeQuery();
        }
        finally {
            con.close();
        }
    }

}

// usage
    public void doSomeStuff() throws SQLException {
        MyDAOWrapper dao = new MyDAOWrapper(ds, new MyDAO());
        dao.exec();
    }
关于错误处理,除非捕获异常,否则不需要重新抛出异常。如果连接存在,那么finally子句应该关闭该连接,当该连接退出时,异常将继续向上传播

try {
  do_something();
}
finally {
  cleanup();
  // throw is not necessary
}

您可以创建一个包装器或父类来管理连接,这样就不必在每个方法中复制逻辑。这里有一个示例说明,我实际上并没有编译或测试它

public interface DAOClass {
    public void execSomeQuery() throws SQLException;
}

public class MyDAOWrapper {
    private DAOClass dao;
    private DataSource ds;

    public MyDAOWrapper(DataSource ds, DAOClass dao) {
        this.dao = dao;
        this.ds = ds;
    }

    public void exec() throws SQLException {
        Connection con = ds.getConnection();
        try {
            dao.execSomeQuery();
        }
        finally {
            con.close();
        }
    }

}

// usage
    public void doSomeStuff() throws SQLException {
        MyDAOWrapper dao = new MyDAOWrapper(ds, new MyDAO());
        dao.exec();
    }
关于错误处理,除非捕获异常,否则不需要重新抛出异常。如果连接存在,那么finally子句应该关闭该连接,当该连接退出时,异常将继续向上传播

try {
  do_something();
}
finally {
  cleanup();
  // throw is not necessary
}

这也意味着我需要捕获每个异常,关闭连接,然后重新抛出异常?这还意味着,每个DAO方法都需要单独获得一个连接,而不是整个DAO类获得一个分配的连接。getConnection是否会导致开销?1是的,捕获每个连接2什么?你不会按自己的方式获得任何东西。池将重用连接这也意味着我需要捕获每个异常,关闭连接,然后重新抛出异常?这还意味着,每个DAO方法都需要单独获得一个连接,而不是整个DAO类获得一个分配的连接。getConnection是否会造成开销?1是的,捕获每个连接2什么?你不会按自己的方式获得任何东西。池将重用这些连接