2017-04-17 71 views
1

我不知道這樣做的最佳實踐,但我的整體問題是,我無法弄清楚,爲什麼我的連接不打烊。連接到SqlServer的不關閉在for循環的Java

我基本上遍歷一個列表,然後將它們插入到一個表中。在我將它們插入表格之前,我會檢查並確保它不是重複的。如果是,我更新行而不是插入它。到目前爲止,在調試讓我知道我的連接不緊密之前,我只能獲得13次迭代。

因爲我有2個連接,我無法搞清楚我猜想關閉我的連接,我試圖用其他的例子來幫助。以下是我的了:

 Connection con = null; 
    PreparedStatement stmt = null; 
    PreparedStatement stmt2 = null; 
    ResultSet rs = null; 
    Connection con2 = null; 


    for (Object itemId: aList.getItemIds()){ 
     try { 
      con = cpds2.getConnection(); 
       stmt = con.prepareStatement("select [ID] from [DB].[dbo].[Table1] WHERE [ID] = ?"); 
       stmt.setInt(1, aList.getItem(itemId).getBean().getID()); 

       rs = stmt.executeQuery(); 
      //if the row is already there, update the data/ 

       if (rs.isBeforeFirst()){ 
        System.out.println("Duplicate"); 
        stmt2 = con2.prepareStatement("UPDATE [DB].[dbo].[Table1] SET " 
        + "[DateSelected]=GETDATE() where [ID] = ?"); 
        stmt2.setInt(1,aList.getItem(itemId).getBean().getID()); 
       stmt2.executeUpdate(); 
       }//end if inserting duplicate 
       else{ 
        con2 = cpds2.getConnection(); 
        System.out.println("Insertion"); 
        stmt.setInt(1, aList.getItem(itemId).getBean().getID()); 

        //Otherwise, insert them as if they were new 
        stmt2 = con.prepareStatement("INSERT INTO [DB].[dbo].[Table1] ([ID],[FirstName]," 
          + "[LastName],[DateSelected]) VALUES (?,?,?,?)"); 
        stmt2.setInt(1,aList.getItem(itemId).getBean().getID()); 
        stmt2.setString(2,aList.getItem(itemId).getBean().getFirstName()); 
        stmt2.setString(3,aList.getItem(itemId).getBean().getLastName()); 
        stmt2.setTimestamp(4, new Timestamp(new Date().getTime())); 
        stmt2.executeUpdate(); 
       }//End Else 
     }catch(Exception e){ 
       e.printStackTrace(); 
      }//End Catch 
     finally{ 
       try { if (rs!=null) rs.close();} catch (Exception e) {} 
      try { if (stmt2!=null) stmt2.close();} catch (Exception e) {} 
      try { if (stmt!=null) stmt.close();} catch (Exception e) {} 
      try { if (con2!=null) con2.close();} catch (Exception e) {} 
      try {if (con!=null) con.close();} catch (Exception e) {} 
      }//End Finally 

    } //end for loop 
    Notification.show("Save Complete"); 

這是我的池連接:

//Pooled connection 
    cpds2 = new ComboPooledDataSource(); 

    try { 
     cpds2.setDriverClass("net.sourceforge.jtds.jdbc.Driver"); 
    } catch (PropertyVetoException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } //loads the jdbc driver 
    cpds2.setJdbcUrl("jdbc:jtds:sqlserver://SERVERNAME;instance=DB"); 
    cpds2.setUser("username"); 
    cpds2.setPassword("password"); 
    cpds2.setMaxStatements(180); 
    cpds2.setDebugUnreturnedConnectionStackTraces(true); //To help debug 
    cpds2.setUnreturnedConnectionTimeout(2); //to help debug 

我的主要問題是,我在結束我聯繫吧?我的連接池是否設置正確? 我應該關閉for循環內部還是外部的連接?

我的c3p0問題?還是JTDS?

+1

IMHO,你應該建立'for'循環外的連接,則循環完成時關閉/退出。否則,您會在每個循環中獲得新的連接。是的,隨着游泳池的緩解,它仍然有很多可以避免的流失。 – alroc

+0

對不起,如果這聽起來像是一個非常愚蠢的問題,但是在關閉之前多次重複使用同一連接上的預備語是安全的嗎? – arsarc

+1

是的。您甚至可以在循環之外準備語句,並且只更新每次迭代中的參數。另外,除非你連接到兩個不同的數據源(並且它看起來不像你),否則你可以放棄'con2'並使用'con'來處理所有事情。潛在的微觀優化,但如果你循環這個很多,它會加起來。 – alroc

回答

1

這是偉大的,你的工作要小心,穩健close()你的資源,但這是過於複雜。

除非你用的是很老的Java版本(之前的Java 7的東西),你可以使用try-with-resources,這確實簡化了這個東西。在一個邏輯單元中使用兩個不同的連接會引起誤解。資源應儘可能在本地使用,而不是將所有內容都推遲到最後。

你的異常處理是危險的。如果發生了一個你不明白的異常,你可能需要打印它的堆棧跟蹤,但是你的代碼應該表明一個事實,即你所做的任何事情都不起作用。你吞下例外,甚至儘管通知「保存完成」。

這一切說,你的生活可能被MERGE聲明,I think SQL Server supports進行容易得多。

下面是一個(未測試的,未編譯的)例如重組:

try (Connection con = cpds2.getConnection()) { 
    for (Object itemId: aList.getItemIds()){ 
     boolean id_is_present = false; 
     try (PreparedStatement stmt = con.prepareStatement("select [ID] from [DB].[dbo].[Table1] WHERE [ID] = ?")) { 
      stmt.setInt(1, aList.getItem(itemId).getBean().getID()); 
      try (ResultSet rs = stmt.executeQuery()) { 
       id_is_present = rs.next(); 
      } 
     } 
     if (id_is_present) { 
      System.out.println("Duplicate"); 
      try (PreparedStatement stmt = con.prepareStatement("UPDATE [DB].[dbo].[Table1] SET [DateSelected]=GETDATE() where [ID] = ?")) { 
       stmt.setInt(1,aList.getItem(itemId).getBean().getID()); 
       stmt.executeUpdate(); 
      } 
     } else { 
      System.out.println("Insertion"); 
      try (PreparedStatement stmt = con.prepareStatement("INSERT INTO [DB].[dbo].[Table1] ([ID],[FirstName], [LastName],[DateSelected]) VALUES (?,?,?,?)")) { 
       stmt.setInt(1,aList.getItem(itemId).getBean().getID()); 
       stmt.setString(2,aList.getItem(itemId).getBean().getFirstName()); 
       stmt.setString(3,aList.getItem(itemId).getBean().getLastName()); 
       stmt.setTimestamp(4, new Timestamp(new Date().getTime())); 
       stmt.executeUpdate(); 
      } 
     } 
    } 
    Notification.show("Save Complete");  
}  
+0

好的,我重寫了我的程序中的連接,以便像嘗試使用資源一樣工作,並且好像連接正在關閉。我真的很驚訝,當我查找與sql創建連接的例子時,我從來沒有發現嘗試使用它們中的資源。它總是嘗試/抓住/最後。謝謝你的回答。 – arsarc