我想在我编写的非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个查询,之后它停止处理与资源分配相关的一些例外!
答案 0 :(得分:2)
如果您正在将应用程序从使用单个缓存连接演变为使用连接池,那么您需要做的主要是......
1)不要将任何Connections存储为对象的静态或成员变量。只存储对DataSource的引用,cpds是上面的代码示例;
2)每次需要使用Connection时,在池支持的DataSource上调用getConnection();
3)确保在每次使用后可靠地关闭()Connection(即在每个资源关闭包含在其自己的try / catch中的finally块中,或者如果您的代码库是Java 7,则通过{{ 3}})。如果你不这样做,你最终会泄漏连接并耗尽池。 c3p0有一些try-with-resources,但最好的建议是不要写漏洞代码。
但是,您要获取单个连接的身份验证应该是您通过池进行身份验证的方式。您是否需要在您的环境中做一些特殊或不寻常的认证?
所以,大问题。
首先是一些可能的结果:System.exit(0)是一种回应异常的坏方法。您的方法接受没有功能的dbName
参数。
但是,一个巨大的,巨大的,糟糕的问题是你没有做任何资源清理。您的executeQuery
和executeUpdate
方法打开了Connections,然后无法关闭()它们。这将导致短期内的资源泄漏。如果要在这些方法中打开Connection,则必须以某种方式返回它们,以便在使用后可以将它们关闭()。那会很麻烦。您可以重新定义接受Connecion对象的方法,例如......
ResultSet executeQuery( Connection con, String query ) {
...
}
......或者更好的是,让你的客户直接使用JDBC api,这实际上比使用实际上做得很少的execute
方法简单得多。
如果您的代码库是Java 7,hacks to help you with that是确保清理JDBC资源的便捷方式。如果没有,你将不得不使用显式finally子句(调用close()最终嵌套在他们自己的try / catches中。)
至于您所看到的例外情况,他们的信息非常明确。您在关闭()编辑后使用ResultSet。问题是为什么。我没有一个简单的答案,但总的来说,你对资源清理并不是很干净;我怀疑这是问题所在。我很惊讶您设法使用此代码运行2000个查询,因为您正在泄漏Connections并且应该已经用完了。所以有一些谜团。但不管怎样,你偶尔会尝试使用ResultSets,因为它们已经被close()编辑,可能还有其他一些Thread。也许你正在做一些非显而易见的事情来关闭()连接,比如使用resultSet.getStatement(),getConnection()来找到你需要关闭的资源(),然后在你完成工作之前关闭()连接使用ResultSet?
祝你好运!