2014-10-30 113 views
0

我想弄清楚如何在類之間共享建立的連接到數據庫以執行不同的SQL語句。 我通讀了一些主題,但由於我對編程相當陌生,所以我很難將給定的信息適應於我的問題。如何在類之間共享數據庫連接? (JDBC)

問題:我有兩個班,一個打開到數據庫的連接,執行一些SQL statments並調用其他類做同樣只使用不同的表和SQL statments。 現在,只要我用他們自己的主要方法分離地運行類,並且連接一切正常。但是,當一個類調用另一個時,我得到不同的異常,這取決於我到目前爲止嘗試的解決方法(MySQLNonTransientConnectionException:數據源拒絕建立連接StackOverflowException)。

這裏是我正在試圖建立了用於在兩個不同的類來執行某些SQL操作的連接:

public ClassA{ 

    public static Connection dbConn; 

    //Set up a connection to the database 
    String dbURL = "jdbc:mysql://<some database>"; //put host, port and database here 
    Properties connectionProbs = new Properties(); 
    connectionProbs.put("user", "root"); //insert USER here 
    connectionProbs.put("password", "root"); //insert PASSWORD here 

    dbConn = null; 
    try{ 
     dbConn = DriverManager.getConnection(dbURL, connectionProbs); 

     PreparedStatement useStmt; 
     try{ 
      useStmt = dbConn.prepareStatement("USE <some database>"); //insert DATABASE here 
      useStmt.executeUpdate(); 
     } 
     catch(SQLException e){ 
      e.printStackTrace(); 
     } 
     //Do some SQL operations 
     //Call class B to do some SQL operations using the same connection 

    } 
    catch(SQLException e){ 
     System.err.println("There was a problem connecting to the database"); 
     e.printStackTrace(); 
    } 
    finally{ 
     if(dbConn != null) 
      try{dbConn.close();}catch(SQLException e){e.printStackTrace();} 
    } 
} 

爲什麼不能B類的ClassA使用的連接,例如通過做這樣的事情(這將導致出現StackOverflow):

PreparedStatement Stmt = ClassA.dbConn.prepareStatement("INSERT INTO table(ID, name) VALUES (?,?)"); 

在另一方面,如果我試圖建立兩個獨立的連接(使用上述同樣的代碼)到同一個數據庫(在運行同時)我得到MySQLNonTransientConnectionException:數據如此urce拒絕建立連接。

處理這個問題的最佳方法是什麼?我在論壇中偶然發現了ConnectionPooling,但是我找不到一個初學者友好的來源來詳細說明如何將其付諸實踐。是否有直接的方法來確保不同的類可以連接和操作一個數據庫?

感謝您的任何反饋

+0

您可以發佈,編譯,並顯示你的問題的代碼?你給了我們一個沒有方法,構造函數或狀態的類,並且只是用某種方法編寫代碼。請給我們真實的代碼。 – RealSkeptic 2014-10-30 12:06:14

+0

你是對的RealSkeptic。我沒有發佈實際的代碼,因爲它超過600行。我不想用不必要的數據向你發送垃圾郵件,但是我意識到所選擇的片段遠非完美(我對編碼沒什麼新意)。我發現stackOVerflow,這是完全不同的東西。我想你們會立即找到它 – SomewhereDave 2014-11-02 22:59:04

回答

0

您可以通過在類A中爲Connection創建一個非靜態全局變量,然後創建一個非靜態公共方法來返回此連接來實現該目的,如下所示。

public ClassA{ 
    // non-static global private Connection object 
    private Connection dbConn = null; 

    // non-static public method to get dbConn connection object 
    public Connection getConnection() { 
     // this condition will check if the Connection is not already open then open it. 
     if(null == dbConn) { 
      //Set up a connection to the database 
      String dbURL = "jdbc:mysql://<some database>"; //put host, port and database here 
      Properties connectionProbs = new Properties(); 
      connectionProbs.put("user", "root"); //insert USER here 
      connectionProbs.put("password", "root"); //insert PASSWORD here 

      try{ 
       dbConn = DriverManager.getConnection(dbURL, connectionProbs); 

       PreparedStatement useStmt; 
       try{ 
        useStmt = dbConn.prepareStatement("USE <some database>"); //insert DATABASE here 
        useStmt.executeUpdate(); 
       } 
       catch(SQLException e){ 
        e.printStackTrace(); 
       } 
       //Do some SQL operations 
       //Call class B to do some SQL operations using the same connection 

      } 
      catch(SQLException e){ 
       System.err.println("There was a problem connecting to the database"); 
       e.printStackTrace(); 
      } 
      finally{ 
       if(dbConn != null) 
        try{dbConn.close();}catch(SQLException e){e.printStackTrace();} 
      } 
     } 
     return dbConn; 
    } 
} 

然後在你的班級B,你可以做這樣的事情。

A a = new A(); 
PreparedStatement Stmt = a.getConnection().prepareStatement("INSERT INTO table(ID, name) VALUES (?,?)"); 

希望這可以幫助你。

+0

謝謝Shishir。我會盡力將其實施到我的程序中。我應該如何將getConnection()方法放入與上面提到的Mark分開的類中? – SomewhereDave 2014-11-02 23:04:57

+0

你可以在同一個類中使用'getConnection()'方法。 – 2014-11-03 09:13:46

0

我會避免把連接放入一個靜態變量。它在你的特定情況下並沒有太大的區別,但最好不要養成這樣做的習慣。

您應該創建一個控制類創建數據庫連接,然後將其作爲方法參數傳遞給其他兩個類。這樣控制類可以處理其他類拋出的任何異常,並確保連接正確關閉。

+0

感謝您的建議馬克。正如我上面所說的,我對編程很陌生。我可以問(對於一個消息來源),如何通過一個連接而不會讓所有的事情都糾纏不清或尋找哪些陷阱? – SomewhereDave 2014-11-02 23:03:36

0

您應該創建一個控制類創建數據庫連接,然後將其作爲方法參數傳遞給其他兩個類。

public class ConnectionManager { 

    private static String url = "jdbc:mysql://localhost:3306/DbName"; 
    private static String username = "YourUsername"; 
    private static String password = "yourDbPass"; 
    private static Connection con; 

    public static Connection getConnection() throws Exception { 
     con = DriverManager.getConnection(url, username, password); 
     return con; 
    } 


} 

public class main { 

    public static void main(String[] args) throws Exception { 
     Connection con = null; 
     con = ConnectionManager.getConnection(); 


     CrudCity s = new CrudCity(); 
     s = s.read(con); 
     System.out.println(s); 

     CrudCountry c = new CrudCountry(); 
     c = c.read(con); 
     System.out.println(c); 

     CrudCountryLanguage lang = new CrudCountryLanguage(); 
     lang = lang.read(con); 
     System.out.println(lang); 


    } 

} 

public class CrudCity extends City implements CrudInterface { 


    public CrudCity read(Connection con) throws Exception{ 
     CrudCity p = new CrudCity(); 

     Statement stmt = con.createStatement(); 
     ResultSet rs = stmt.executeQuery("SELECT ID,Name,CountryCode FROM world.city"); 
     while (rs.next()) { 
      p.setId(rs.getInt("ID")); 
      p.setName(rs.getString("Name")); 
      p.setCountryCode(rs.getString("CountryCode")); 

     } 
     rs.close(); 
     return p; 
    } 
} 

public class CrudCountry extends Country implements CrudInterface{ 

    public CrudCountry read(Connection con) throws Exception{ 
     CrudCountry c = new CrudCountry(); 
     Statement stmt =con.createStatement(); 
     ResultSet rs = stmt.executeQuery("SELECT Code,Name,Continent FROM world.country"); 
     while (rs.next()) { 
      c.setCountryCode(rs.getString("Code")); 
      c.setCountryName(rs.getString("Name")); 
      c.setCodeContinent(rs.getString("Continent")); 
     } 

     rs.close(); 

     return c; 
    } 
} 
+0

通過方法共享連接 read(Connection con) – user3414054 2016-11-10 16:00:17