2017-09-16 75 views
1

將C3P0管理連接重置爲其初始狀態的建議方法是什麼?重置JDBC連接狀態(c3p0)

我正在使用Microsoft JDBC驅動程序並在一個連接上設置SET ROWCOUNT 1。這會導致連接執行的所有查詢僅返回一行,即使連接已返回到池並稍後再次獲取。我是否應該明確重置值onCheckinonCheckout

主類

import com.mchange.v2.c3p0.ComboPooledDataSource; 
import java.beans.PropertyVetoException; 
import java.sql.SQLException; 
import java.sql.Statement; 

import java.sql.Connection; 
import java.sql.ResultSet; 

public class Main { 

    final ComboPooledDataSource cpds; 

    Main() throws PropertyVetoException { 
     cpds = new ComboPooledDataSource(); 
     cpds.setDriverClass("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 
     cpds.setJdbcUrl("jdbc:sqlserver://10.42.62.41:1433;databaseName=mach;integratedSecurity=false;SendStringParametersAsUnicode=true;applicationName=panda;"); 
     cpds.setUser("testuser"); 
     cpds.setPassword("welcome123"); 
     cpds.setInitialPoolSize(0); 
     cpds.setMinPoolSize(1); 
     cpds.setMaxPoolSize(1); 
     cpds.setConnectionCustomizerClassName("C3p0ConnectionCustomizer"); 
     cpds.setDescription("Netbeans test project"); 
    } 

    Connection getConnection() throws SQLException{ 
     return cpds.getConnection(); 
    } 

    public static void main(String[] args) throws PropertyVetoException, SQLException { 
     Main m = new Main(); 

     try(Connection connection = m.getConnection()){ 
      Statement stmt = connection.createStatement(); 
      stmt.execute("SET ROWCOUNT 1"); 
     } 

     try(Connection connection = m.getConnection()){ 
      try(Statement stmt = connection.createStatement()) { 
       int cnt = 0, rsCnt = 0; 
       boolean results = stmt.execute("select * from Foo; select * from Bar"); 
       if(results) { 
        do { 
         rsCnt++; 
         ResultSet rs = stmt.getResultSet(); 
         while(rs.next()) { 
          cnt++; 
         } 
         System.out.println(rsCnt + " -> " + cnt); 
         rs.close(); 
         results = stmt.getMoreResults(); 
         cnt = 0; 
        } while (results); 
       } 
      } 
     } 

    } 

} 

定製 - 主要是看所使用的連接。

import com.mchange.v2.c3p0.AbstractConnectionCustomizer; 
import java.sql.Connection; 
import java.sql.SQLException; 
import java.sql.Statement; 

public class C3p0ConnectionCustomizer extends AbstractConnectionCustomizer { 

    @Override 
    public void onAcquire(Connection c, String pdsIdt) { 
     try (Statement stmt = c.createStatement()) { 
      stmt.execute("SET ROWCOUNT 0"); 
     } catch(SQLException sqle) { 
      sqle.printStackTrace(); 
     } 
    } 

    @Override 
    public void onCheckOut(Connection c, String pdsIdt) { 
     System.out.println("Checked out " + c + " [" + pdsIdt + "]"); 
    } 

    @Override 
    public void onCheckIn(Connection c, String pdsIdt) throws SQLException { 
     System.out.println("Checking in " + c + " [" + pdsIdt + "]"); 

    } 

} 

如果沒有SET ROWCOUNT 1行,上述查詢會返回更多行。定製程序日誌記錄顯示正在使用相同的連接。

回答

1

有人可能會爭辯說,理想情況下,調用SET ROWCOUNT 1的代碼確實應該「自行清理」,確保它在將連接釋放回池之前調用SET ROWCOUNT 0

但是,如果我們不能絕對保證這種行爲,那麼將您的SET ROWCOUNT 0調用從onAcquire方法簡單地移動到onCheckIn方法似乎是相當合理的。即使重置ROWCOUNT並不是真的必要,但它會導致每次入住的額外往返行程,但SET ROWCOUNT 0將是相對便宜的操作。

(我只是c3p0-0.9.5.2和MSSQL-JDBC試了一下,移動SET ROWCOUNT 0onCheckIn方法了預期的效果。)

+0

難道不是更好重置價值onCheckIn而非onCheckOut?我從c3p0文檔瞭解到checkin是異步處理的,而checkout本質上是同步的。 – calvinkrishy

+0

@calvinkrishy - 好點。我已經更新了我的答案。 –