【问题标题】:How to properly close MySql database connection如何正确关闭 MySql 数据库连接
【发布时间】:2016-11-23 21:26:20
【问题描述】:

在我的 Web 应用程序中,我有单独的类 DataAccess.java 和 DBUtils.java。

我在 DBUtils.jva 中有以下代码

public static PreparedStatement getPreparedStatement(String sql) throws ClassNotFoundException, SQLException{
    PreparedStatement ps = null;
    Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost:3306/company";
    String user = "root";
    String pass = "root";

    Connection con = DriverManager.getConnection(url, user, pass);
    ps = con.prepareStatement(sql);       

    return ps;

我在 DataAccess.java 类中有以下代码

public static List<Company> getAllCompanies(){
    List<Company> ls = new LinkedList<>();

    try {
        String sql = "select * from company";
        ResultSet rs = DBUtils.getPreparedStatement(sql).executeQuery();            
        while (rs.next()){
            Company cp = new Company (rs.getInt(1), rs.getString(2), rs.getInt(3),rs.getTimestamp(9));
            ls.add(cp);
        }
        rs.close();            
    } catch (ClassNotFoundException | SQLException ex) {
        Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
    }

    return ls;
}

我正在从不同的 servlet 调用 getAllCompanies 函数。我不知道如何正确关闭数据库连接,因为它是在一个类中打开并从另一个类中调用的。由于与数据库的打开连接过多,我的 Web 应用程序不断崩溃,错误说,

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:数据源拒绝建立连接,来自服务器的消息:“连接太多”

有人可以告诉我在这种情况下如何正确关闭数据库连接。

【问题讨论】:

    标签: java mysql


    【解决方案1】:

    你只是关闭了结果集

    但你没有关闭连接。

    在 finally 块中请做

    con.close()
    

    更多信息请参考:Closing Database Connections in Java

    【讨论】:

      【解决方案2】:

      基本上,您不会关闭正在创建连接泄漏的数据库connection 对象。所以你需要修改你的DBUtil方法为getConnection(),如下所示。

      总是closefinally 块中的资源(connection、preparedstatement 和resultset 对象)如下所示,否则它会造成连接泄漏,很快你就会用完连接数。

      DBUtil getConnection():

      public static Connection getConnection() throws ClassNotFoundException, SQLException{
          PreparedStatement ps = null;
          Class.forName("com.mysql.jdbc.Driver");
          String url = "jdbc:mysql://localhost:3306/company";
          String user = "root";
          String pass = "root";
      
          Connection con = DriverManager.getConnection(url, user, pass);
          return con;
      }
      

      getAllCompanies() 代码:

      public static List<Company> getAllCompanies(){
          List<Company> ls = new LinkedList<>();
          PreparedStatement pstmt = null;
          ResultSet rs = null;
          Connection conn = null;
          try {
              String sql = "select * from company";
               conn = DBUtils.getConnection();
               pstmt = conn.prepareStatement(sql);       
              rs = pstmt.executeQuery();            
              while (rs.next()){
                  Company cp = new Company (rs.getInt(1), rs.getString(2), rs.getInt(3),rs.getTimestamp(9));
                  ls.add(cp);
              }
      
          } catch (ClassNotFoundException | SQLException ex) {
              Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
          } finally {
              if(rs != null) {
                   rs.close();
              }
              if(pstmt !=null) {
                 pstmt.close();
              } 
              if(conn != null) {
                 conn.close();
              }
          }
          return ls;
      }
      

      另外,我强烈建议您在DBUtil 类中创建closeConnection()、closeResultSet()、closePreparedStatement() 等方法,以避免所有方法中的样板代码。 p>

      【讨论】:

      • 非常感谢。这很有意义。你会在 closeConnection() 、 closeResultSet() 和 closePreparedStatement() 等方法中写什么。因为只需要一行来关闭它们,如果我创建这些方法和 DBUtils,无论如何都需要一行来调用它们。你有什么建议。
      【解决方案3】:

      我现在在 DBUtils.java 类中有以下代码我有以下方法

      public static void closeResultSet(ResultSet rs) throws ClassNotFoundException, SQLException {
          if(rs != null) {
              try {
                  rs.close();
              } catch (SQLException ex) {
                  Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
              }
          }
      }   
      
      public static void closePreparedStatement(PreparedStatement ps) throws ClassNotFoundException, SQLException {
          if(ps != null) {
              try {
                  ps.close();
              } catch (SQLException ex) {
                  Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
              }
          }
      }  
      
      public static void closeConnection(Connection conn) throws ClassNotFoundException, SQLException {
          if(conn != null) {
              try {
                  conn.close();
              } catch (SQLException ex) {
                  Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
              }
          }
      }  
      

      在我的 DataAccess.java 类中,

      public static List<Company> getAllCompanies(){
          List<Company> ls = new LinkedList<>();
          ResultSet rs = null;
          PreparedStatement ps = null;        
          Connection conn = null;
          try {
              String sql = "select * from company";
              conn = DBUtils.getConnection();
              ps = conn.prepareStatement(sql);
              rs = ps.executeQuery();
              while (rs.next()){
                  Company cp = new Company (rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getTimestamp(9));
                  ls.add(cp);
              }
          } catch (ClassNotFoundException | SQLException ex) {
              Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
          }finally {
              DBUtils.closeResultSet(rs);
              DBUtils.closePreparedStatement(ps);
              DBUtils.closeConnection(conn);
          }
      

      我还没有编译它,但我认为它应该没问题。再次感谢您的帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-14
        • 2012-03-29
        • 2015-01-26
        • 2018-01-30
        • 1970-01-01
        • 1970-01-01
        • 2010-09-24
        相关资源
        最近更新 更多