重置JDBC连接状态(c3p0)

时间:2017-09-16 09:19:53

标签: sql-server jdbc c3p0

将C3P0受管连接重置为初始状态的推荐方法是什么?

我正在使用Microsoft JDBC驱动程序并在一个连接上设置SET ROWCOUNT 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 个答案:

答案 0 :(得分: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 0移动到onCheckIn方法会产生预期效果。)