2017-09-16 5 views
1

Quelle est la méthode recommandée pour réinitialiser une connexion gérée C3P0 à son état initial? J'utilise le pilote Microsoft JDBC et le SET ROWCOUNT 1 sur une connexion. Cela entraîne que toutes les requêtes exécutées par cette connexion ne renvoient qu'une seule ligne même après que la connexion a été renvoyée au pool et qu'elle a été récupérée plus tard. Dois-je réinitialiser les valeurs explicitement onCheckin ou onCheckout?Réinitialisation d'un état de connexion JDBC (c3p0)

Classe principale

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); 
       } 
      } 
     } 

    } 

} 

Customizer - Principalement pour voir la connexion utilisée.

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 + "]"); 

    } 

} 

Sans la ligne SET ROWCOUNT 1, plusieurs lignes sont renvoyées par les requêtes ci-dessus. La journalisation du personnaliseur indique que la même connexion est utilisée.

Répondre

1

On pourrait argumenter que, idéalement, le code qui appelle SET ROWCOUNT 1 devrait vraiment "nettoyer après lui-même" en s'assurant qu'il appelle SET ROWCOUNT 0 avant de relâcher la connexion au pool.

Cependant, si nous de la méthode onAcquire ne peut pas garantir absolument un tel comportement, alors il semble tout à fait raisonnable de déplacer simplement votre SET ROWCOUNT 0 appel à la méthode onCheckIn. Il en résulterait un aller-retour supplémentaire pour chaque enregistrement, même si la réinitialisation ROWCOUNT n'était pas vraiment nécessaire, mais un SET ROWCOUNT 0 serait une opération relativement peu coûteuse.

(Je viens d'essayer avec c3p0-0.9.5.2 et MSSQL-jdbc, et le déplacement SET ROWCOUNT 0 à la méthode onCheckIn eu l'effet désiré.)

+0

Ne serait-il pas préférable de réinitialiser la valeur onCheckIn plutôt que onCheckOut? Je comprends des docs de c3p0 que Checkin est manipulé de façon asynchrone tandis que le contrôle est synchrone dans la nature. – calvinkrishy

+0

@calvinkrishy - Bon point. J'ai mis à jour ma réponse. –