使用单例类,Tomcat,C3P0在Java Web应用程序中管理池化数据源

时间:2012-02-16 10:55:28

标签: java singleton datasource connection-pooling c3p0

我有一个在Blackboard学习软件中运行的java Web应用程序,它使用Tomcat 5.5。 该应用程序连接到外部数据库。

我无权在Blackboard服务器上声明数据源,因此我尝试将所有内容打包到Web应用程序中。尽管在使用后小心地关闭了所有结果集,语句和连接,但我的基于commons的池化方法出现了连接问题。 我现在正在切换到C3P0池方法,但我不确定我的一般方法是否正确。

我使用单例类来创建数据源,目的是最小化实现连接池的数据源的创建和销毁。以下课程应该清楚地说明这一点。这是一种合理的方法,还是可能导致我之前的连接用完了?

感谢。

EDIT。更新的问题,以澄清单身方法的目的。我每次需要数据库连接时都试图避免创建数据源。这似乎使连接池的好处无效。

数据源类:

import java.beans.PropertyVetoException;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import com.mchange.v2.c3p0.*;

public class MyDataSource {

private static MyDataSource mds = new MyDataSource();
public static DataSource ds;

private MyDataSource() {
    try {
        ds = getDataSource();
    } catch (NamingException e) {
        e.printStackTrace();
    }
}

public static MyDataSource getInstance(){
    return mds;
}

public Connection getConnection() throws SQLException, NamingException {
    Connection myConnect = ds.getConnection();
    return myConnect;
}

private DataSource getDataSource() throws NamingException {

    ComboPooledDataSource cpds = new ComboPooledDataSource(); 
    try {
        cpds.setDriverClass( "com.mysql.jdbc.Driver" );
    } catch (PropertyVetoException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    cpds.setJdbcUrl( "jdbc:mysql://195.195.xx.xx:3306/dbName" ); 
    cpds.setUser("lemmy"); 
    cpds.setPassword("xxx");
    cpds.setMaxIdleTime(180);
    cpds.setMaxPoolSize(100);       
    return cpds;
}
 }

连接类:

import java.sql.*;
import javax.sql.*;
import javax.naming.*;

public class DbConnection {

public Connection c;

public DbConnection() throws NamingException, SQLException {
    c = getConnection();
}

public Connection getConnection() throws SQLException, NamingException {        
    Connection myConnect = MyDataSource.getInstance().getConnection();
    return myConnect;       
}

public void close(){
    JDBCUtils.close(this.c);
}
}

关闭连接等。

import java.sql.*;

public class JDBCUtils {

static public void close (ResultSet rs) {
    try { if (rs!=null) rs.close(); } catch (Exception e) {}
    }

  //  Works for PreparedStatement also since it extends Statement.
  static public void close (Statement stmt) {
    try { if (stmt!=null) stmt.close(); } catch (Exception e)   {}
    }

  static public void close (java.sql.Connection conn) {
    try { if (conn!=null) conn.close(); } catch (Exception e) {}
    }   

}

使用示例:

    String myQuery = null;
    DbConnection myConnect = null;
    Statement myStatement = null;
    ResultSet rs = null;

    try {
       myConnect = new DbConnection();
        myStatement = myConnect.c.createStatement();

                // Do stuff here

        }catch (SQLException e) {
    out.println("SQL Error: "+e);
    } finally {
        JDBCUtils.close(rs);
        JDBCUtils.close(myStatement);
        myConnect.close();
    }

2 个答案:

答案 0 :(得分:1)

您可能希望从spring框架中查看JdbcTemplate。您可以单独使用它,因为Spring声称提供了许多帮助程序类。这为连接/语句/结果集嵌套问题提供了简化。它也更简单地处理查询。

我知道出于学习目的,你可能不会使用JdbcTemplate,但是类设计很有趣。

在汇集时,已经有@duffymo的答案。

答案 1 :(得分:0)

我认为这在各方面都是错误的想法。

您希望连接池中有多个连接。让池管理生命周期;它将分摊每个请求的创建成本。

单身人士将意味着每个人都有一个请求。这对我来说毫无意义。

您的应用应以这种方式使用连接:每个请求一个。获取它,使用它,在单个方法的范围内将其返回到池中。它会以更好的方式扩展。您也可以编写更少的代码。将其设置为JNDI数据资源,你就可以了。