MYSQL 尽管正确关闭资源,但获取数据的连接过多

MYSQL Getting Data too many connections in-spite of closing resources properly

我正在使用 mysql 5.0,我经常收到数据太多连接错误,我确信我正在关闭我的 finally 块中的所有连接

这是我的 class 用于获取数据库连接

public class DBConnection {

    final static Logger logger = Logger.getLogger(DBConnection.class);
     private static DataSource dataSource;
        static {
            try {
                  dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/REDEX");
            } catch (NamingException e) {
                logger.error("NamingException Occured" , e);
                e.printStackTrace();
                try {
                  //  throw new Exception("'jndifordbconc' not found in JNDI",e);

                } catch (Exception e1) {

                    //logger.error("Exception Occured" , e1);
                    logger.error("NamingException Occured" , e1);
                        e1.printStackTrace();

                }
            }
        }

        public static Connection getDBConnection() {
            try {
                return dataSource.getConnection();
            } catch (SQLException e) {
                logger.error("Exception Occured Under getDBConnection" , e);
                return null;
            }

        }


    public static void close(Connection con)
    {
        if (con != null)
        {
            try
            {
                con.close();
            }
            catch (SQLException e)
            {
                logger.error("Exception Occured inside close " , e);
            }
        }
    }

    public static void close(Statement stmt, ResultSet rs) 
    {
        if (rs != null)
        {
            try
            {
                rs.close();
            }
            catch (SQLException e)
            {
                logger.error("Exception Occured while closing resultset " , e);
            }
        }
        if (stmt != null)
        {
            try
            {
                stmt.close();
            }
            catch (SQLException e)
            {
                logger.error("Exception Occured while closing statement " , e);
            }
        }
    }
}

连接池设置

<ResourceLink name="jdbc/REDEX"
                global="jdbc/REDEX"
                type="javax.sql.DataSource" />

<Resource name="jdbc/REDEX"
      global="jdbc/REDEX"
      type="javax.sql.DataSource"
      auth="Container"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/REDEX?allowMultiQueries=true"
     factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
      username="root"
      password="xxxxx@123"
    initialSize="100"
      maxActive="100"
      maxIdle="20"
     minIdle="10"
    suspectTimeout="60"
    timeBetweenEvictionRunsMillis="30000"
    minEvictableIdleTimeMillis="60000"
   validationQuery="SELECT 1"
   validationInterval="34000"
  testOnBorrow="true"
   removeAbandoned="true"
  removeAbandonedTimeout="55"
  />

示例 java class 我如何使用连接和关闭

public class GetBrands {
    final static Logger logger = Logger.getLogger(GetBrands.class);
    @GET
    @Consumes("application/text")
    @Produces("application/json")
    public String getAllBrands() throws JSONException 
    {
        logger.error("the GetBrands got called");
        Connection dbConnection = null;
        PreparedStatement getAllBrandsPst = null ;
        ResultSet getAllBrandsResltSet = null;
        JSONArray jsonarray_listedBrands = new JSONArray();
        JSONObject jsonObj_allbrands = new JSONObject();
        try
        {
            dbConnection = DBConnectionOrient.getDBConnection();
            getAllBrandsPst = dbConnection.prepareStatement("select distinct listedBrandName,listedbrandID from tbl_listedBrand  group by listedBrandName");
            getAllBrandsResltSet = getAllBrandsPst.executeQuery();
            while(getAllBrandsResltSet.next())
            {
                //
            }
            jsonObj_allbrands.put("brands", jsonarray_listedBrands);
        }
        catch(Exception e)
        {
            logger.error("Exception Occured" , e);
        }
        finally
        {
            DBConnectionOrient.close(getAllBrandsPst,getAllBrandsResltSet);
            DBConnectionOrient.close(dbConnection);
        }

        String  response = "jsonCallback("+jsonObj_allbrands.toString()+")";
        return response;
    }
}

这是我在日志中遇到的异常

SEVERE: Unable to create initial connections of pool.
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1014)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1110)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2465)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2498)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2283)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:822)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
    at sun.reflect.GeneratedConstructorAccessor10.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:404)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:317)
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:278)
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:701)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:635)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:486)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:144)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
    at org.apache.tomcat.jdbc.pool.DataSourceFactory.createDataSource(DataSourceFactory.java:554)
    at org.apache.tomcat.jdbc.pool.DataSourceFactory.getObjectInstance(DataSourceFactory.java:242)
    at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:141)
    at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:842)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:830)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
    at org.apache.catalina.core.NamingContextListener.addResource(NamingContextListener.java:1103)
    at org.apache.catalina.core.NamingContextListener.createNamingContext(NamingContextListener.java:682)
    at org.apache.catalina.core.NamingContextListener.lifecycleEvent(NamingContextListener.java:271)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:731)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:689)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:321)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)

如果有多个我可以这样走吗

finally {
    try {
        DBConnectionOrient.close(getAllBrandsPst,getAllBrandsResltSet);
 DBConnectionOrient.close(getAllBrandsPst2,getAllBrandsResltSet2);
    } catch (Exception e) {}
    try {
        DBConnectionOrient.close(dbConnection);
    } catch (Exception e) {}
}

我发现您的代码存在一个潜在问题,可能 是某些未关闭的悬挂数据库连接的来源。我提请您注意以下两行代码:

DBConnectionOrient.close(getAllBrandsPst,getAllBrandsResltSet);
DBConnectionOrient.close(dbConnection);

认识到如果在第一次调用DBConnectionOrient.close()语句和结果集时发生异常,那么数据库连接将永远不会关闭。更安全的方法如下:

finally {
    try {
        DBConnectionOrient.close(getAllBrandsPst,getAllBrandsResltSet);
    } catch (Exception e) {}
    try {
        DBConnectionOrient.close(dbConnection);
    } catch (Exception e) {}
}

现在,即使关闭语句和结果集出现问题,仍然会尝试关闭数据库连接。

以下是您在 JDBC 通话中应遵循的一般模因:

Connection con = null;
Statement stmt = null;
ResultSet rs = null;

try {
    // get a connection, statement and result set, in this order
    // make your JDBC calls here
} catch (Exception e) {
    // handle all exceptions here
} finally {
     try {
         try {rs.close();} catch (Exception e) {}
         try {stmt.close();} catch (Exception e) {}
          // Note that we will attempt to close the database connection even
          // if something went wrong with closing the statement or result set
         try {con.close();} catch (Exception e) {}
     } catch (Exception e) {  }
}