2015-06-15 48 views
-1

我正在使用以下代碼連接到我的簡單jsp/servlet登錄項目(即單例)的數據庫。當我第一次登錄時,它在我登出成功後有效。現在問題開始時,我再次嘗試登錄錯誤提出說「嚴重:錯誤消息:連接關閉後不允許任何操作」。 但是,當我刪除代碼關閉連接它再次正常工作。請建議我使用它還是避免它。Singleton是否適用於servlet/jsp項目?

public class ConnectionMgr { 

    private static ConnectionMgr instance = null; 

    private static final String USERNAME = "root"; 
    private static final String PASSWORD = ""; 
    private static final String M_CONN_STRING = "jdbc:mysql://localhost:3306/generator"; 
    private static final String H_CONN_STRING = "jdbc:hsqldb:data/generator"; 

    private DBType dbType = DBType.MYSQL; 

    private Connection conn = null; 


    private ConnectionMgr() { 
    } 

    public static ConnectionMgr getInstance() { 
     if (instance == null) { 
      instance = new ConnectionMgr(); 
     } 
     return instance; 
    } 

    public void setDBType(DBType dbType) { 
     this.dbType = dbType; 
    } 

    private boolean openConnection() { 
     try { 
      switch (dbType) { 

       case MYSQL: 
        Class.forName("com.mysql.jdbc.Driver"); 
        conn = DriverManager.getConnection(M_CONN_STRING, USERNAME, PASSWORD); 
        return true; 

       case HSQL: 
        conn = DriverManager.getConnection(H_CONN_STRING, USERNAME, PASSWORD); 
        return true; 

       default: 
        return false; 
      } 
     } catch (SQLException | ClassNotFoundException e) { 
      System.err.println(e); 
      DBUtil.processException((SQLException) e); 
      return false; 
     } 
    } 

    public Connection getConnection() { 
     if (conn == null) { 
      if (openConnection()) { 
       System.out.println("Connection opened"); 
       return conn; 
      } else { 
       return null; 
      } 
     } 
     return conn; 
    } 

    public void processException(SQLException e) { 
     System.err.println("Silgleton connection()Error -->"); 
     System.err.println("Erroe message:" + e.getMessage()); 
     System.err.println("Error code:" + e.getErrorCode()); 
     System.err.println("Error State:" + e.getSQLState()); 
    } 

    public void close() { 
     System.out.println("Closing connection"); 
     try { 
      conn.close(); 
      conn = null; 
     } catch (Exception e) { 
     } 
    } 
} 
+0

我對單身人士的批評之一是他們導致的問題完全是這樣的,其中包含的對象的生命週期變得未知,當不適當的應用程序設計。當從Web服務器進行任何數據庫訪問時,您可能需要有多個連接到數據庫才能處理併發請求。這就是爲什麼使用RDBMS的原因 - 它們允許你做到這一點。因爲客戶端代碼被允許關閉連接,所以Singleton實際上失去了控制權,並且隨後的代碼將它斷開。 –

+0

另外,您應該爲每個數據庫事務使用新的連接,然後立即關閉它們;這樣,您可以建立訪問控制,根據需要關閉自動提交(針對單個事務中的多個查詢),如果發生錯誤則回滾事務,並確保合理的原子更新以及其他細節。通過重新使用連接而沒有正確管理其狀態,您將爲各種問題打開大門。 –

回答

1

您的連接管理器不是線程安全的。因此,當一個用戶嘗試使用單個實例讀取數據時,另一個用戶的線程可能會最終關閉正在使用的連接。

取而代之的是使用類似Apache DBCP的東西,它也會給你一個連接池。

如果您仍想使用上面的代碼,請將連接管理器更改爲常規對象而不是單例。

+0

感謝您的幫助。 – user3811169

0

您可能正在保存對第一個請求的「連接」實例的引用,然後爲第二個請求重新使用該引用。

每次有新的請求進入servlet時,都要確保你調用了getConnection()

在您的ConnectionMgr類的所有方法中添加一個System.out.println("your-method-name-")

+0

thankx很多先生,現在亞姆明確,如果我使用相同的代碼爲桌面應用程序? – user3811169

相關問題