2017-09-16 15 views
1

C3P0管理接続を初期状態にリセットするには、どのような方法が推奨されますか?JDBC接続状態のリセット(c3p0)

私は、Microsoft JDBCドライバを使用して、接続にSET ROWCOUNT 1を設定しています。これにより、接続がプールに返された後でも、その接続によって実行されたすべてのクエリが1つの行を返すようになり、その後に再びがフェッチされます。値を明示的にonCheckinまたはonCheckoutにリセットする必要がありますか?

メインクラス

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が呼び出されていることを確認することで、実際に「クリーンアップ」する必要があります。 コールをonAcquireメソッドからonCheckInメソッドに単純に移動することは、非常に妥当と思われます。 ROWCOUNTを本当にリセットする必要がなくても、SET ROWCOUNT 0が比較的安価な操作であっても、チェックインごとに余分な往復が発生します。

(私はちょうどc3p0-0.9.5.2とMSSQL-JDBCでそれを試みたが、onCheckIn方法にSET ROWCOUNT 0を移動すると、所望の効果を持っていた。)

+0

むしろonCheckOutよりも値をonCheckInリセットする方が良いと思いませんか?私はチェックインが非同期的に扱われるのに対し、checkoutは本質的に同期的であることをc3p0ドキュメントから理解しています。 – calvinkrishy

+0

@calvinkrishy - 良い点。私は私の答えを更新しました。 –