使用c3p0的java连接池
我想在我编写的无web应用程序java程序中使用c3p0进行连接池。我使用了传统的单例连接,我对它的性能不满意,所以我决定使用连接池。我看了一下c3p0网站,下面是他们关于使用c3p0的介绍:
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("swaldman");
cpds.setPassword("test-password");
// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
// The DataSource cpds is now a fully configured and usable pooled DataSource
我想知道如何将其用于ms sql windows身份验证连接,但我不知道如何使用?另外,如何通过该连接设置查询?似乎使用连接池与传统的数据库连接是一个完全不同的世界,对此我是新手。 以下是我得出的结论:
public class DatabaseManager {
private static DataSource dataSource;
private static final String DRIVER_NAME;
private static final String URL;
private static final String UNAME;
private static final String PWD;
private static final String dbName;
static {
dbName="SNfinal";
DRIVER_NAME = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
URL = "jdbc:sqlserver://localhost:1433;" +
"databaseName="+dbName+";integratedSecurity=true";
UNAME = "";
PWD = "";
dataSource = setupDataSource();
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
private static DataSource setupDataSource() {
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass(DRIVER_NAME);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
cpds.setJdbcUrl(URL);
cpds.setUser(UNAME);
cpds.setPassword(PWD);
cpds.setMinPoolSize(1000);
cpds.setAcquireIncrement(1000);
cpds.setMaxPoolSize(20000);
return cpds;
}
public static ResultSet executeQuery(String SQL, String dbName)
{
ResultSet rset = null ;
try {
Connection con=DatabaseManager.getConnection();
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
rset = st.executeQuery(SQL);
}
catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}
return rset;
}
public static void executeUpdate(String SQL, String dbName)
{
try {
Connection con=DatabaseManager.getConnection();
Statement st = con.createStatement();
st.executeUpdate(SQL);
}
catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}
}
}
当我使用这个类时,它可以很好地处理大约2000个查询,之后它会停止处理与资源分配相关的一些异常
# 1 楼答案
如果您正在将应用程序从使用单个缓存连接演变为使用连接池,那么您必须做的主要事情是
1)不要将任何连接存储为对象的静态或成员变量。只存储对数据源的引用,cpds是上面的代码示例
2)每次需要使用连接时,在池支持的数据源上调用getConnection()
3)确保在每次使用后可靠地关闭()连接(即,在finally块中,每个资源都封装在自己的try/catch中,或者,如果您的代码库是Java 7,则通过try-with-resources)如果不这样做,您最终会泄漏连接并耗尽池中的气体。c3p0有一些hacks to help you with that,但最好的建议是不要编写泄漏代码
但是,通过池进行身份验证以获取单个连接的方式应该是。您是否必须在您的环境中执行一些特殊或不寻常的身份验证
所以,大问题
首先是一些零碎的东西:系统。退出(0)不是响应异常的好方法。您的方法接受没有函数的
dbName
参数但是一个大的、巨大的、坏的问题是,你没有做任何资源清理。您的
executeQuery
和executeUpdate
方法打开连接,然后无法关闭它们。这将在短期内导致资源泄漏。如果您想在这些方法内部打开连接,您必须以某种方式返回它们,以便在使用后可以关闭它们。那会变得很麻烦。您可以重新定义接受Connecion对象的方法,也就是说,类似于。。。或者更好的是,让您的客户机直接使用JDBCAPI,这实际上比使用
execute
方法要简单得多,因为实际上execute
方法做的很少如果您的代码库是Java7,try-with-resources是确保清理JDBC资源的方便方法。否则,您将不得不使用显式finally子句(在finally中对close()的调用嵌套在它们自己的try/catch中)
至于你看到的例外情况,他们的信息很清楚原因。在结果集关闭()之后,您正在使用它们。问题是为什么。我没有一个简单的答案,但总的来说,你对资源清理不是很干净;我想这就是问题所在。我很惊讶你能用这段代码运行2000个查询,因为你正在泄漏连接,应该已经用完了。所以这里有一些谜团。但不管怎样,您偶尔会尝试在结果集被关闭()后使用它们,可能是由其他线程完成的。也许您正在做一些不明显的事情来关闭()连接,比如使用resultSet。getStatement()、getConnection()以查找需要关闭()的资源,然后在使用完ResultSet之前关闭()连接
祝你好运