【问题标题】:Cache JDBC connections缓存 JDBC 连接
【发布时间】:2017-01-25 18:49:58
【问题描述】:

我有一个非常依赖数据库的小型电子商务应用程序。我已经看到了一些性能问题,主要是在建立与数据库的连接时。我不是 DBA,也不是任何其他深入的 DB 知识 - 但我知道缓存连接而不是一直建立新连接是有意义的。

以下是我获取连接的方法:

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 创建新连接?

谢谢。

【问题讨论】:

    标签: java mysql tomcat servlets jdbc


    【解决方案1】:

    在您有一个相当大的电子商务应用程序的情况下,您通常不会按照您在代码中显示的方式编写数据库连接。

    我们使用连接池。

    我猜,您的电子商务应用程序将部署在某个应用程序服务器中,使用该服务器的连接池设施来管理您的数据库连接。

    如果它是一个没有服务器的应用程序,您可以使用 C3P0 等连接池 API 之一来显式编码池功能。

    我猜你所说的连接缓存基本上是要求实现一个单例。 Internet上有很多关于如何实现单例的示例,但是您不应该在代码中关闭连接。

    有一个叫做 connection-timeout 时间的东西,如果使用单连接缓存解决方案,您需要正确设置它。

    希望对你有帮助!!

    【讨论】:

    • 非常感谢,这对我来说是新事物:)
    • 我认为人们在这里的支持不够,所以我尽我所能来改变它;-)
    【解决方案2】:

    您需要的是一个连接池,您可以在Tomcat 中轻松配置开箱即用,这样连接池将直接由Tomcat 管理,从而避免大量集成问题,保证完全兼容并避免添加新的依赖项。

    以下是要遵循的步骤:

    1。全局定义连接池

    conf/contex.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。为你的 webapp 声明你的连接池

    在您的 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的Common ClassLoader中可用,因为它是一个全局资源,因此您需要将驱动程序的jar放在tomcat/lib


    更多关于JNDI数据源的细节Tomcathere

    【讨论】:

      【解决方案3】:

      您可以使用如下所示的单例类:

      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()call 期间创建连接并将其缓存在conn 字段中。稍后DBHandler.getConnection() 调用将返回此缓存连接。

      如果您的应用程序需要处理大量数据库请求,请同时阅读连接池。

      【讨论】:

      • 这是一个非常糟糕的建议。对于大型应用程序,您不使用单例连接:您使用连接池。
      • 我明白这一点,我已经在我的回答中指出了这一点。我实际上是在回复他的问题how can I easily cache a current connection and reuse it instead of creating a new one using JDBC/Java? 这个问题也被标记为tomcat。我从未见过大型电子商务网站在 Tomcat 上运行。所以我认为他是从零开始,正在寻找基本信息
      • 按照您在答案中显示的操作可能只在单用户应用程序中有意义,而不是在可以并发访问的应用程序中。
      • 您关于线程安全的 cmets 让我了解了更多细节,并从 stackoverflow.com/questions/6507687/… 中获得了一些见解。谢谢您
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 2012-07-26
      • 1970-01-01
      • 2014-08-03
      • 1970-01-01
      • 2018-05-01
      • 2011-08-15
      相关资源
      最近更新 更多