简体   繁体   English

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

[英]Managing pooling datasource in Java web app with singleton class, Tomcat, C3P0

I have a java web app running in Blackboard learning software, which uses Tomcat 5.5. 我有一个在Blackboard学习软件中运行的Java Web应用程序,该软件使用Tomcat 5.5。 The app connects to an external database. 该应用程序连接到外部数据库。

I don't have access to declare a datasource on the Blackboard server, so I am trying to package everything in the web app. 我无权在Blackboard服务器上声明数据源,因此我尝试将所有内容打包在Web应用程序中。 I have had a problem with my commons-based pooling approach running out of connections, in spite of carefully closing all resultsets, statements and connections after use. 尽管在使用后仔细关闭了所有结果集,语句和连接,但我的基于公用的池化方法在连接用尽时还是遇到了问题。 I am now switching to a C3P0 pooling method, but I'm not sure that my general approach is correct. 我现在正在切换到C3P0池化方法,但是我不确定我的一般方法是否正确。

I am using a singleton class to create a datasource, with the aim of minimizing the creation and destruction of datasources which implement connection pooling. 我正在使用一个singleton类来创建数据源,目的是最大程度地减少实现连接池的数据源的创建和销毁。 The following classes should illustrate this clearly. 以下课程应清楚地说明这一点。 Is this a reasonable approach, or is it likely to have contributed to my previous problem of running out of connections? 这是一种合理的方法,还是可能导致了我以前用尽连接的问题?

Thanks. 谢谢。

EDIT. 编辑。 Updated question to clarify purpose of singleton approach. 更新了问题以阐明单例方法的目的。 I am trying to avoid creating a datasource everytime I need a db connection. 我试图避免每次需要数据库连接时都创建数据源。 This seems to nullify the benefits of having connection pooling. 这似乎使拥有连接池的好处无效。

Datasource class: 数据源类:

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;
}
 }

Connection class: 连接类别:

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);
}
}

Closing connections etc. 关闭连接等

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) {}
    }   

}

Example usage: 用法示例:

    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();
    }

You might want to look at JdbcTemplate from the spring framework. 您可能想从spring框架中查看JdbcTemplate You can use it standalone, as Spring has the claim to provide many helper classes. 您可以独立使用它,因为Spring声称可以提供许多帮助程序类。 That provides a simplification for the connection/statement/resultset nesting problem. 这简化了连接/语句/结果集嵌套问题。 Also it handles the querying simpler. 而且它处理查询更简单。

I know for learning purposes you probably won't use JdbcTemplate, but the class design is interesting. 我知道出于学习目的,您可能不会使用JdbcTemplate,但是类设计很有趣。

On pooling there already is an answer from @duffymo. 关于池化,@ duffymo已经提供了答案。

I think this is the wrong idea in every way. 我认为这在所有方面都是错误的想法。

You want multiple connections in a connection pool. 您需要一个连接池中的多个连接。 Let the pool manage the lifecycle; 让池管理生命周期; it'll amortize the creation cost over every request. 它将分摊每个请求的创建成本。

A singleton will mean one request for every one. 单身意味着每一个请求。 That makes no sense to me. 这对我来说毫无意义。

Your app should use connections this way: one per request. 您的应用应以这种方式使用连接:每个请求一个。 Acquire it, use it, return it to the pool in the scope of a single method. 获取并使用它,然后将其返回到单个方法范围内的池中。 It'll scale better that way. 这样可以更好地扩展。 Less code for you to write as well. 更少的代码供您编写。 Set it up as a JNDI data resource and you're good to go. 将其设置为JNDI数据资源,就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM