有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用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. # 1 楼答案

    如果您正在将应用程序从使用单个缓存连接演变为使用连接池,那么您必须做的主要事情是

    1)不要将任何连接存储为对象的静态或成员变量。只存储对数据源的引用,cpds是上面的代码示例

    2)每次需要使用连接时,在池支持的数据源上调用getConnection()

    3)确保在每次使用后可靠地关闭()连接(即,在finally块中,每个资源都封装在自己的try/catch中,或者,如果您的代码库是Java 7,则通过try-with-resources如果不这样做,您最终会泄漏连接并耗尽池中的气体。c3p0有一些hacks to help you with that,但最好的建议是不要编写泄漏代码

    但是,通过池进行身份验证以获取单个连接的方式应该是。您是否必须在您的环境中执行一些特殊或不寻常的身份验证


    所以,大问题

    首先是一些零碎的东西:系统。退出(0)不是响应异常的好方法。您的方法接受没有函数的dbName参数

    但是一个大的、巨大的、坏的问题是,你没有做任何资源清理。您的executeQueryexecuteUpdate方法打开连接,然后无法关闭它们。这将在短期内导致资源泄漏。如果您想在这些方法内部打开连接,您必须以某种方式返回它们,以便在使用后可以关闭它们。那会变得很麻烦。您可以重新定义接受Connecion对象的方法,也就是说,类似于

    ResultSet executeQuery( Connection con, String query ) { 
      ...
    }
    

    。。。或者更好的是,让您的客户机直接使用JDBCAPI,这实际上比使用execute方法要简单得多,因为实际上execute方法做的很少

    如果您的代码库是Java7,try-with-resources是确保清理JDBC资源的方便方法。否则,您将不得不使用显式finally子句(在finally中对close()的调用嵌套在它们自己的try/catch中)

    至于你看到的例外情况,他们的信息很清楚原因。在结果集关闭()之后,您正在使用它们。问题是为什么。我没有一个简单的答案,但总的来说,你对资源清理不是很干净;我想这就是问题所在。我很惊讶你能用这段代码运行2000个查询,因为你正在泄漏连接,应该已经用完了。所以这里有一些谜团。但不管怎样,您偶尔会尝试在结果集被关闭()后使用它们,可能是由其他线程完成的。也许您正在做一些不明显的事情来关闭()连接,比如使用resultSet。getStatement()、getConnection()以查找需要关闭()的资源,然后在使用完ResultSet之前关闭()连接

    祝你好运