重置 JDBC 连接状态 (c3p0)
Resetting a JDBC connection state (c3p0)
将 C3P0 托管连接重置为其初始状态的推荐方法是什么?
我正在使用 Microsoft JDBC 驱动程序并在一个连接上设置 SET ROWCOUNT 1
。这会导致该连接执行的所有查询 return 只有一行 即使在连接已 return 进入池并稍后再次获取 之后也是如此。我应该明确地重置值 onCheckin
还是 onCheckout
?
主要class
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 - 主要是看正在使用的连接。
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
行,更多行将被上述查询 return 编辑。定制程序日志显示正在使用相同的连接。
有人可能会争辩说,理想情况下,调用 SET ROWCOUNT 1
的代码确实应该 "clean up after itself",方法是确保在将连接释放回池之前调用 SET ROWCOUNT 0
。
但是,如果我们不能绝对保证这种行为,那么将您的 SET ROWCOUNT 0
调用从 onAcquire
方法简单地移动到 onCheckIn
方法似乎是很合理的。这将导致每次签到都要额外往返一次,即使重置 ROWCOUNT
并不是真正必要的,但 SET ROWCOUNT 0
将是一个相对便宜的操作。
(我刚刚用 c3p0-0.9.5.2 和 mssql-jdbc 试了一下,将 SET ROWCOUNT 0
移动到 onCheckIn
方法达到了预期的效果。)
将 C3P0 托管连接重置为其初始状态的推荐方法是什么?
我正在使用 Microsoft JDBC 驱动程序并在一个连接上设置 SET ROWCOUNT 1
。这会导致该连接执行的所有查询 return 只有一行 即使在连接已 return 进入池并稍后再次获取 之后也是如此。我应该明确地重置值 onCheckin
还是 onCheckout
?
主要class
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 - 主要是看正在使用的连接。
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
行,更多行将被上述查询 return 编辑。定制程序日志显示正在使用相同的连接。
有人可能会争辩说,理想情况下,调用 SET ROWCOUNT 1
的代码确实应该 "clean up after itself",方法是确保在将连接释放回池之前调用 SET ROWCOUNT 0
。
但是,如果我们不能绝对保证这种行为,那么将您的 SET ROWCOUNT 0
调用从 onAcquire
方法简单地移动到 onCheckIn
方法似乎是很合理的。这将导致每次签到都要额外往返一次,即使重置 ROWCOUNT
并不是真正必要的,但 SET ROWCOUNT 0
将是一个相对便宜的操作。
(我刚刚用 c3p0-0.9.5.2 和 mssql-jdbc 试了一下,将 SET ROWCOUNT 0
移动到 onCheckIn
方法达到了预期的效果。)