2015-04-27 297 views
3

我的DAO對象關閉連接

package com.myselect; 

import java.sql.*; 
import java.sql.DriverManager; 

import java.util.logging.Level; 
import java.util.logging.Logger; 

public class DataAccess { 

    Connection conn; 
    PreparedStatement pst; 
    ResultSet rs; 

    public DataAccess() { 
     try { 
      Class.forName("com.mysql.jdbc.Driver"); 
      conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost/db", "root", "root"); 
     } catch (ClassNotFoundException ex) { 
      Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (SQLException ex) { 
      Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex); 
     } 

    } 

    public String getAge(String name) { 
     String userage = null; 
     try { 
      pst = conn.prepareStatement("select age from mydb where name= ?"); 
      pst.setString(1, name); 

      rs = pst.executeQuery(); 

      while (rs.next()) { 
       userage = rs.getString("age"); 
       System.out.println(userage); 
      } 

     } catch (Exception ex) { 
      Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex); 
     } 

     return userage; 
    } 

    public int insertRecord(String name, int addage) { 
     int b = 0; 
     try { 
      pst = conn.prepareStatement("insert into mydb values(?,?)"); 
      pst.setString(1, name); 
      pst.setInt(2, addage); 
      b = pst.executeUpdate(); 

     } catch (Exception ex) { 
      Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex); 
     } 

     return b; 
    } 


} 

我想關閉連接。我有幾個servlet調用了insertRecordgetAge方法。關閉我的連接的最佳方式是什麼?創建另一個方法並從insertRecordgetAge方法調用或在構造函數中?

+0

爲什麼不能有2種方法,第一個打開JDBC資源,二來關閉它們? – Arvind

+0

你順便提一下另一個主要問題:壓制異常並繼續,就像沒有任何異常發生一樣。這樣,servlet永遠不會意識到DAO調用是成功還是失敗,因此無法顯示錯誤頁面或消息。另請參閱此示例的另一個答案:http://stackoverflow.com/questions/5003142/jsp-using-mvc-and-jdbc – BalusC

回答

1

在考慮連接之前,您還應該始終使用關閉每次使用它們時的對象ResultSetStatement。請勿將它們保存爲DataAccess對象中的狀態。讓他們爲本地變量和使用後關閉它們:

public String getAge(String name) { 
    PreparedStatement pst = null; 
    ResultSet rs = null; 
    String userage = null; 
    try { 
     pst = conn.prepareStatement("select age from mydb where name= ?"); 
     pst.setString(1, name); 

     rs = pst.executeQuery(); 

     while (rs.next()) { 
      userage = rs.getString("age"); 
      System.out.println(userage); 
     } 

    } catch (Exception ex) { 
     Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex); 
    } finally { 
     // closing JDBC resources 
     if(rs != null) { 
      rs.close(); 
     } 

     if(pst != null) { 
      pst.close(); 
     } 

    return userage; 
} 

同爲連接:在理想情況下,每一個方法應該創建一個Connection對象及其使用後關閉它。根據您在方法中打開和關閉連接的頻率,您可能希望使用連接池來共享打開的連接以提高效率。

對於關閉連接和資源,您可以創建做到這一點的方法:

public void closeConnection(Connection connection, Statement statement, ResultSet resultSet) { 
    ... // close resources here 
} 
+0

如果我有更多的方法,那麼我需要添加重複代碼,如 Connection c = null;等一次又一次的所有方法? 不能有一個解決方案,我可以調用一個靜態方法來關閉所有的連接? –

+0

@ChandlerChrisPratt當然,您可以將方法中的關閉進行分組,也可以使用相同的方法從頭開始或從池中檢索連接。 – manouti

1

需要時應打開和關閉連接。在你的情況下,你在一個點上打開一個連接,然後在另一個點上使用它。這意味着你打開了一個連接,並可能在一段時間內不使用它。

你需要做的是讓方法自成一體,這意味着方法應該打開連接,完成後關閉它。關閉部分應在finally區塊內完成,這將確保無論發生什麼情況,該集合將始終關閉。

事情是這樣:

public String getAge(String name) { 
     String userage = null; 
     Connection conn = null; 
     try { 
      Class.forName("com.mysql.jdbc.Driver"); 
      conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost/db", "root", "root"); 

      PreparedStatement pst = conn.prepareStatement("select age from mydb where name= ?"); 
      pst.setString(1, name); 

      rs = pst.executeQuery(); 

      while (rs.next()) { 
       userage = rs.getString("age"); 
       System.out.println(userage); 
      } 

     } catch (Exception ex) { 
      Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     finally { 
      if(conn != null) { 
       conn.close(); 
      } 

      if(pst != null) { 
       pst.close(); 
      } 

      if(rs != null) { 
       rs.close(); 
      } 
     } 

     return userage; 
    } 

編輯:按照@virtualpathum建議,你也可以看看第三方的框架,它爲您提供的手段來管理你的連接池,通常是通過的實施Singleton編程模式。

+0

您可以嘗試使用單例設計模式來創建連接。只是一個建議。 – virtualpathum

+0

好的,在這裏我們不關閉結果集和準備語句。這不影響任何東西嗎? 我讀了一些結果集可以佔據一些空間取決於我們的查詢 –

+0

@ChandlerChrisPratt:是的,你需要關閉它們。我很快會修改代碼。 – npinti