2016-11-23 53 views
0

在我的Web應用程序中,我有單獨的類DataAccess.java和DBUtils.java。如何正確關閉MySql數據庫連接

我在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:數據源拒絕建立連接,來自服務器的消息:「連接太多」

有人請告訴我如何在這種情況下正確關閉數據庫連接。

回答

0

基本上,你是不是關閉數據庫connection對象被創建的連接泄漏。因此,您需要將DBUtil方法修改爲getConnection(),如下所示。

始終closefinally塊的資源(connectionpreparedstatementresultset對象),如下圖所示,否則會造成連接泄漏,很快你就會用完連接。

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; 
} 

另外,我強烈建議你創建像closeConnection()方法,closeResultSet()closePreparedStatement()在您的DBUtil類中以避免所有方法中的樣板代碼。

+0

非常感謝。它非常有意義。你會用closeConnection(),closeResultSet()和closePreparedStatement()方法編寫什麼東西。因爲它只需要一行來關閉它們,並且如果我創建了這些方法和DBUtils,則無論如何都需要一行來調用它們。你有什麼建議。 – Monauwar

0

我現在下面的代碼在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); 
    } 

我還沒有編譯它,但是我覺得它應該沒問題。再次感謝您的幫助。