2011-12-13 152 views
2

我正在創建一個連接到多個數據庫的java應用程序。用戶將能夠從下拉框中選擇他們想要連接的數據庫。Java連接到多個數據庫

程序然後通過將名稱傳遞給創建初始上下文的方法來連接到數據庫,以便它可以與Oracle Web邏輯數據源進行通信。

public class dbMainConnection { 

    private static dbMainConnection conn = null; 
    private static java.sql.Connection dbConn = null; 
    private static javax.sql.DataSource ds = null; 
    private static Logger log = LoggerUtil.getLogger(); 

    private dbMainConnection(String database) { 

     try { 

      Context ctx = new InitialContext(); 

      if (ctx == null) { 
       log.info("JDNI Problem, cannot get InitialContext"); 
      } 

       database = "jdbc/" + database; 
       log.info("This is the database string in DBMainConnection" + database); 
       ds = (javax.sql.DataSource) ctx.lookup (database); 


     } catch (Exception ex) { 
      log.error("eMTSLogin: Error in dbMainConnection while connecting to the database : " + database, ex); 
     } 

    } 

    public Connection getConnection() { 

     try { 

      return ds.getConnection(); 

     } catch (Exception ex) { 
      log.error("Error in main getConnection while connecting to the database : ", ex); 
      return null; 
     } 

    } 

    public static dbMainConnection getInstance(String database) { 

     if (dbConn == null) { 
      conn = new dbMainConnection(database); 
     } 

     return conn; 

    } 

    public void freeConnection(Connection c) { 
     try { 
      c.close(); 
      log.info(c + " is now closed"); 
     } catch (SQLException sqle) { 
      log.error("Error in main freeConnection : ", sqle); 
     } 
    } 

} 

我的問題是如果有人忘記爲數據庫創建數據源但是仍將其添加到下拉框中會發生什麼?現在發生的情況是,如果我嘗試連接到沒有數據源的數據庫,那麼它會報錯,無法獲得連接。這是我想要的,但如果我連接到一個數據庫,它首先有一個數據源,它可以工作,然後嘗試連接到沒有數據源的數據庫,它又出錯

javax .naming.NameNotFoundException:無法解析'jdbc.peterson'。解決'jdbc';剩餘的名字'彼得森'。

再次我希望,但什麼是混淆我是它,然後抓住最後一次正確的連接,也就是針對不同的數據庫,並處理一切,彷彿什麼都沒有發生。

任何人都知道這是爲什麼?是weblogic緩存連接還是作爲失敗安全的東西?以這種方式建立聯繫是不是一個好主意?

+0

您是否嘗試將dbMainConnection的捕獲範圍中的ds值清空? –

回答

4

您正在將類中的唯一數據源(和連接以及dbMainConnection)存儲在靜態變量中。每次有人要求數據源時,都要用新數據源替換前一個數據源。如果從JNDI獲取數據源時發生異常,則靜態數據源將保持原樣。你不應該在靜態變量中存儲任何東西。由於您的dbMainConnection類是使用數據庫的名稱構建的,並且有多個數據庫名稱,因此將其設置爲單例是沒有意義的。

只需使用下面的代碼來訪問數據源:

public final class DataSourceUtil { 
    /** 
    * Private constructor to prevent unnecessary instantiations 
    */ 
    private DataSourceUtil() { 
    } 

    public static DataSource getDataSource(String name) { 
     try { 
      Context ctx = new InitialContext(); 
      String database = "jdbc/" + name; 
      return (javax.sql.DataSource) ctx.lookup (database); 
     } 
     catch (NamingException e) { 
      throw new IllegalStateException("Error accessing JNDI and getting the database named " + name); 
     } 
    } 
} 

而讓來電者獲得從數據源的連接並關閉它,當他們使用完。

+0

太棒了。謝謝您的幫助。很明顯,我是一個java newb,所以非常感謝你的明確解釋和代碼。只是爲了確保我明白。我擺脫了dbconnect類,而是使用dataSourceUtil類來獲取數據源。然後用它創建我對不同數據庫的連接。 Afterwords關閉數據庫連接和初始上下文。是對的嗎? – enderjs

+0

正確(除了InitialContext關閉,您無法關閉,但我認爲它不會打開它)。 –

0

查找不存在的數據源時,您正在捕獲JNDI異常,但您的單例仍然保留對之前查找的數據源的引用。作爲A.B.凱德說,除了特例之外,甚至在此之前,對空白的參照都是空的。

在更一般的說明中,也許使用Singleton並不是最好的主意。