【问题标题】:What is wrong with this class for getting connection from database pool此类从数据库池获取连接有什么问题
【发布时间】:2016-01-20 17:52:18
【问题描述】:

我编写了一个类来从数据库池中获取连接 (HikariCP)。我搜索了错误,这意味着连接已关闭。但是,我无法弄清楚问题所在。我确定我在代码中做错了什么,可能没有正确关闭连接或其他原因,因为一段时间后我开始收到如下错误:

11:27:58.843 [http-apr-8080-exec-10] WARN  c.z.h.u.ConcurrentBag -
**Attempt to remove an object from the bag that does not exist: com.mysql.jdbc.JDBC4Connection@5f3145e5, created Oct 21, 11:27:12.734, last release 0ms ago, NOT_IN_USE 11:27:58.861 [http-apr-8080-exec-10] ERROR c.p.d.DAOConnectionFactory - Error while closing connection.** java.sql.SQLException: Connection is closed   at com.zaxxer.hikari.proxy.ClosedConnection$1.invoke(ClosedConnection.java:51) ~[HikariCP-2.4.1.jar:na]     at com.sun.proxy.$Proxy4.clearWarnings(Unknown Source) ~[na:na]     at com.zaxxer.hikari.proxy.ConnectionProxy.close(ConnectionProxy.java:197) ~[HikariCP-2.4.1.jar:na]     at com.presence.dao.DAOConnectionFactory.closeConnection(DAOConnectionFactory.java:73)
**~[DAOConnectionFactory.class:na]   11:28:01.133 [http-apr-8080-exec-9] WARN  c.z.h.p.ConnectionProxy - HikariPool-0 - Connection com.mysql.jdbc.JDBC4Connection@46fb3f92, created Oct 21, 11:27:12.781, last release 28ms ago, IN_USE marked as broken because of SQLSTATE(08003), ErrorCode(0) com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.   at** sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_45]   at 

下面是类:

public class DAOConnectionFactory {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DAOConnectionFactory.class);
    private static final String databaseJNDI = "jdbc/presencedb";
    private static DataSource dataSource = null;
    private static Context context = null;
    private static Connection conn = null;

    private DAOConnectionFactory() {
        System.out.println("Initialized");
    }

    private static DataSource getDataSource() {
        if (dataSource != null) {
            return dataSource;
        }
        try {
            context = new InitialContext();

            if (context == null) {
                context = new InitialContext();
            }

            dataSource = (DataSource) context.lookup("java:comp/env/" + databaseJNDI);
        } catch (NamingException e) {
            logger.error("Error while creating datasource.", e);
        }
        return dataSource;
    }

    protected static Connection getConnection() {
        try {
            conn = getDataSource().getConnection();
        } catch (SQLException e) {
            logger.error("Error while getting database connection.", e);
        }
        return conn;
    }

    protected static void closeConnection(Connection connection, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                logger.error("Error while closing resultset.", e);
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                logger.error("Error while closing statement.", e);
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.error("Error while closing connection.", e);
            }
        }
    }
}

hikaricp 属性:

cachePrepStmts="true" 
defaultAutoCommit="true" 
description="Presence database." 
driverClassName="com.mysql.jdbc.Driver" 
factory="com.zaxxer.hikari.HikariJNDIFactory" 
global="jdbc/presencedb" 
jdbcUrl="jdbc:mysql://192.168.254.167/presence" 
maxWaitMillis="10000" maximumPoolSize="30" 
name="jdbc/presencedb" 
password="" 
prepStmtCacheSize="50" 
prepStmtCacheSqlLimit="512" 
removeAbandoned="true" 
removeAbandonedTimeout="300" 
type="javax.sql.DataSource" 
idleTimeout="25200000"
maxLifetime="25200000"
username="root"

添加这是我获取连接的方式

Connection connection = null;
PreparedStatement preparedStatement = null;
connection = DAOConnectionFactory.getConnection();
preparedStatement = connection.prepareStatement(SQL_UPDATE);

DAOConnectionFactory.closeConnection(connection, preparedStatement, null);

当我执行负载测试时总是会发生这种情况,否则对于少数随机查询我没有注意到这一点。 HikariCP 版本是 2.4.1。

【问题讨论】:

  • 难以辨认。请正确格式化该异常的混乱,即使用代码格式化功能并按原样保留换行符。

标签: java mysql jdbc connection-pooling hikaricp


【解决方案1】:

不要将 Connection 声明为静态,它们会在您的压力测试或分布式环境中导致冲突,您的最终代码看起来像

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import com.itextpdf.text.log.LoggerFactory;

public class DAOConnectionFactory {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DAOConnectionFactory.class);
    private static final String databaseJNDI = "jdbc/presencedb";
    private static DataSource dataSource = null;
    private static Context context = null;
    private Connection conn = null;

    public DAOConnectionFactory() {
        System.out.println("Initialized");
    }

    static {
        if (dataSource == null) {
            try {
                context = new InitialContext();

                if (context == null) {
                    context = new InitialContext();
                }

                dataSource = (DataSource) context.lookup("java:comp/env/" + databaseJNDI);
            } catch (NamingException e) {
                logger.error("Error while creating datasource.", e);
            }
        }
    }

    public Connection getConnection() {
        try {
            conn = dataSource.getConnection();
        } catch (SQLException e) {
            logger.error("Error while getting database connection.", e);
        }
        return conn;
    }

    protected static void closeConnection(Connection connection, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                logger.error("Error while closing resultset.", e);
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                logger.error("Error while closing statement.", e);
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.error("Error while closing connection.", e);
            }
        }
    }
}

和电话一样

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {

    public static String SQL_UPDATE = "query";

    public DAOConnectionFactory factory = new DAOConnectionFactory();

    public static void main(String args[]){
        Main instanceppl = new Main();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        connection = instanceppl.factory.getConnection();
        try {
            preparedStatement = connection.prepareStatement(SQL_UPDATE);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        instanceppl.factory.closeConnection(connection, preparedStatement, null);

    }

}

【讨论】:

    猜你喜欢
    • 2011-05-28
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多