缓存 JDBC 连接

3
我有一个小型的电子商务应用程序,它非常依赖于数据库。我已经发现了一些性能问题,主要是在建立与数据库的连接时。虽然我不是DBA或者其他深入的数据库知识人士,但我知道缓存连接而不是每次都建立新连接是有意义的。
下面是我的获取连接方法:
public Connection getConnection() throws SQLException, ClassNotFoundException  {
    Class.forName("com.mysql.jdbc.Driver"); 
    con=DriverManager.getConnection("jdbc:mysql://182.31.456.32:3306/"+database+"",""+username+"",""+password+""); 
   // stm=con.createStatement(); 
    return con;
}

我的问题是 - 我如何轻松地缓存当前连接并重复使用它,而不是使用JDBC / Java创建新连接?谢谢。
3个回答

6
在一个相当大的电子商务应用中,通常不会像你展示的代码那样编写数据库连接。我们会使用连接池。我猜你的电子商务应用程序将被部署在某个应用服务器上,使用该服务器的连接池功能来管理数据库连接。如果这是一个没有服务器的应用程序,您可以使用连接池API之一,如C3P0等显式地编写池功能。我猜你所谓的连接缓存实际上是要求实现单例。互联网上会有许多关于如何实现单例的示例,但你不应该在代码中关闭连接。有一个叫做连接超时的东西,如果采用单个连接缓存解决方案,需要正确设置它。希望对你有所帮助!

非常感谢,这对我来说是新鲜事物 :) - Sabir Khan
1
我认为这里的人们没有投足够的赞,所以我会尽自己的一份力来改变这种情况;-) - GhostCat

3
你需要的是一个连接池,在Tomcat中可以轻松配置,这样连接池将直接由Tomcat管理,避免了许多集成问题,保证完全兼容性并避免添加新依赖项。
以下是要遵循的步骤:
1. 全局定义连接池
在`conf/context.xml`中,你需要将你的连接池定义为`Resource`。例如,在你的情况下,它可能是这样的:
<Context>

    ...
    <Resource name="jdbc/myPool" auth="Container" type="javax.sql.DataSource"
                initialSize="5" maxActive="20" minIdle="5" maxIdle="15" maxWait="10000"
                validationQuery="SELECT 1" validationQueryTimeout="5"
                testWhileIdle="true" testOnBorrow="true" testOnReturn="false"
                timeBetweenEvictionRunsMillis="30000" minEvictableIdleTimeMillis="60000"
                removeAbandoned="true" removeAbandonedTimeout="300" logAbandoned="false"
                poolPreparedStatements="true"
                username="myUsername" password="myPassword"
                driverClassName="com.mysql.jdbc.Driver" 
                url="jdbc:mysql://182.31.456.32:3306/mydb?autoReconnect=true" />
</Context>

2. 声明你的Web应用程序连接池

在你的Web应用程序的web.xml文件中,你需要使用下面的resource-ref本地定义它:

<web-app>
    ...
    <resource-ref>
        <res-ref-name>jdbc/myPool</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
    ...
</web-app>

3. 从代码中访问我的数据源

您可以使用JNDI访问您的DataSource

Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myPool");
Connection conn = ds.getConnection();

4. 部署你的 JDBC 驱动程序

由于 JDBC 驱动程序是全局资源,所以需要将其放置在 Tomcat 的 公共类加载器 中,使其可以作为全局资源使用,因此你需要将驱动程序的 jar 文件放置在 tomcat/lib 目录下。


关于 TomcatJNDI 数据源的更多细节,请参考这里


-1
您可以使用以下类似单例模式的类:
public class DBHandler{

    private static Connection conn = null;

    private DBHandler(String connString){
        Class.forName("com.mysql.jdbc.Driver"); 
        conn=DriverManager.getConnection(connString);    
    }

    public static void getConnection(String connString) {
        if (conn == null)
            new DBHandler(String connString);
        return conn;
    }
}

在第一次调用DBHandler.getConnection()时,它将创建连接并将其缓存在conn字段中。后续的DBHandler.getConnection()调用将返回此缓存的连接。

如果您的应用程序需要处理大量的数据库请求,请了解连接池技术。


这是非常糟糕的建议。对于大规模应用程序,您不使用单例连接:而是使用连接池。 - Mark Rotteveel
我理解了这一点,并在我的答案中指出了这一点。实际上,我是在回答他的问题“如何轻松缓存当前连接并重复使用它,而不是使用JDBC / Java创建新连接?” 此外,该问题被标记为“tomcat”。我从未见过在tomcat上运行大型电子商务网站。因此,我假设他是从头开始,并正在寻找基本信息。 - Fayaz
1
在你的回答中所展示的操作可能只在单用户应用中有意义,而在可能存在并发访问的应用中则无效。 - Mark Rotteveel
你对线程安全的评论让我深入了解了更多细节,并从这里获得了一些见解:https://dev59.com/G2w15IYBdhLWcg3wmc8J。非常感谢你。 - Fayaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接