2017-09-16 61 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 - 好点。我已经更新了我的答案。 –