JDBC连接池中的数据源未返回连接

时间:2019-01-17 10:59:13

标签: jsp servlets jdbc jndi

我有一个jsp Web应用程序。我正在使用jdbc连接池来使用位于服务器端的mysql数据库。我的Web应用程序有时会挂起,当我检查调试时发现它挂在ds.getConnection();上。它不返回任何异常/错误。浏览器将仅处于加载状态。我已经包含了我的DBConnection类,该类用于创建dadasource和从数据源获取连接。我正在调用getConnection();从池中获取连接的方法。我叫closeConnection();在所有jsp方法中,最后阻塞关闭连接。所以我假设一旦我关闭连接,连接就会返回到池中

public class DBConnection {

public static Connection con = null;
public static String user_id = null;
public static DataSource ds = null;

public static Connection getConnection() {
    try {
        con = ds.getConnection();
        con.setAutoCommit(false);
    } catch (SQLException ex) {
        Logger.getLogger(DBConnection.class.getName()).log(Level.SEVERE, null, ex);
    }
    return con;
}

static {
    con = establishConnection();
}

public static void closeConnection() {
    if (con != null) {
        try {
            if (!con.isClosed()) {
                try {
                    con.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DBConnection.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(DBConnection.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
}

Context.xml

<Context path="/KnestAdmin">
     <Resource name="dbconn" auth="Container" type="javax.sql.DataSource"
            maxActive="100" maxIdle="30" maxWait="10000"
            removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"
            username="root" password="" driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/mobitute_lms_data?useEncoding=true&amp;characterEncoding=UTF-8"/>
</Context>

web.xml

<resource-env-ref>
    <description>DB Connection</description>
    <resource-env-ref-name>dbconn</resource-env-ref-name>
    <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
    <res-auth>Container</res-auth>
</resource-env-ref>

示例servlet来说明我如何使用连接

public class Category extends HttpServlet {

    Connection connection = null;
    Statement statement = null;
    IST ist;
    PrintWriter out;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        out = response.getWriter();
    }

    public void connectToServer() throws SQLException, NamingException {
        connection = DBConnection.getConnection();
        statement = connection.createStatement();
        ist = new IST();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
        try {
            connectToServer();
            switch (request.getParameter("mode")) {
                case "checkAvailability": {
                    String category_name = request.getParameter("category_name");
                    String sql = "Select category_name from course_category where category_name='" + category_name + "'";
                    ResultSet resultset_val = statement.executeQuery(sql);
                    if (resultset_val.next()) {
                        out.print("exist");
                    }
                    break;
                }
                case "checkAvailability1": {
                    String category_id = request.getParameter("category_id");
                    String category_name = request.getParameter("category_name");
                    String sql = "Select category_name from course_category where category_name='" + category_name + "' and category_id!='" + category_id + "'";
                    ResultSet resultset_val = statement.executeQuery(sql);
                    if (resultset_val.next()) {
                        out.print("exist");
                    }
                    break;
                }
                case "checkwarning": {
                    String category_id = request.getParameter("category_id");
                    String warning = "";
                    String sql_query = "select * from course where category_id='" + category_id + "' and status='Active'";
                    ResultSet resultset_val = statement.executeQuery(sql_query);
                    if (resultset_val.next()) {
                        warning = "yes";
                    }
                    String sql_query1 = "select * from assessment where category_id='" + category_id + "' and status='Active'";
                    ResultSet resultset_val1 = statement.executeQuery(sql_query1);
                    if (resultset_val1.next()) {
                        warning = "yes";
                    }
                    if (warning.equals("yes")) {
                        throw new Exception();
                    }
                    break;
                }
                case "active_inactive": {
                    String category_id = request.getParameter("category_id");
                    String status = request.getParameter("status");
                    String sql = "Update course_category set status='" + status + "',last_updated_user='" + request.getSession(false).getAttribute("log_user_id") + "',last_updated_ts='" + ist.getLastUpdatedts() + "' where category_id='" + category_id + "'";
                    int i = statement.executeUpdate(sql);
                    if (i > 0) {
                    }
                    connection.commit();
                    break;
                }
                default:
                    break;
            }
        } catch (Exception ex) {
            Logger.getLogger(Category.class.getName()).log(Level.SEVERE, null, ex);
            try {
                response.setStatus(400);
                if (!connection.isClosed()) {
                    connection.rollback();
                }
            } catch (SQLException ex1) {
                Logger.getLogger(Category.class.getName()).log(Level.SEVERE, null, ex1);
            }
        } finally {
            try {
                out.flush();
                out.close();
                if (!statement.isClosed()) {
                    statement.close();
                }
                DBConnection.closeConnection();
                connection=null;
            } catch (SQLException ex) {
                Logger.getLogger(Category.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
        try {
            connectToServer();
            switch (request.getParameter("mode")) {
                case "add": {
                    String category_name = request.getParameter("category_name");
                    String category_desc = request.getParameter("category_desc");
                    String status = request.getParameter("status");
                    String sql = "INSERT INTO course_category(category_name,category_desc,status,created_user,created_ts,last_updated_user,last_updated_ts) VALUES ('" + category_name + "',  '" + category_desc + "','" + status + "','" + request.getSession(false).getAttribute("log_user_id") + "','" + ist.getLastUpdatedts() + "','" + request.getSession(false).getAttribute("log_user_id") + "','" + ist.getLastUpdatedts() + "')";
                    statement.executeUpdate(sql);
                    connection.commit();
                    break;
                }
                case "edit": {
                    String category_id = request.getParameter("category_id");
                    String category_name = request.getParameter("category_name");
                    String category_desc = request.getParameter("category_desc");
                    String sql = "update course_category set category_name='" + category_name + "',category_desc='" + category_desc + "',last_updated_user='" + request.getSession(false).getAttribute("log_user_id") + "',last_updated_ts='" + ist.getLastUpdatedts() + "' where category_id='" + category_id + "'";
                    statement.executeUpdate(sql);
                    connection.commit();
                    break;
                }
                default:
                    break;
            }
        } catch (Exception ex) {
            try {
                Logger.getLogger(Category.class.getName()).log(Level.SEVERE, null, ex);
                if (ex instanceof SQLIntegrityConstraintViolationException) {
                    response.setStatus(1);
                }else{
                    response.setStatus(2);
                }
                if (!connection.isClosed()) {
                    connection.rollback();
                }
            } catch (SQLException ex1) {
                Logger.getLogger(Category.class.getName()).log(Level.SEVERE, null, ex1);
            }
        } finally {
            try {
                out.flush();
                out.close();
                if (!statement.isClosed()) {
                    statement.close();
                }
                DBConnection.closeConnection();
                connection=null;
            } catch (SQLException ex) {
                Logger.getLogger(Category.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

2 个答案:

答案 0 :(得分:0)

您忘记了close the connection

  

使用finally语句关闭池化连接。在适用于使用池连接的代码的try / catch块之后,将出现以下finally块:

try {
     Connection con = 
  ds.getConnection(username, password);
     // ... code to use the pooled
     // connection con
 } catch (Exception ex {
     // ... code to handle exceptions
 } finally {
     if (con != null) con.close();
 }

您的数据源已达到定义的最大连接数。

答案 1 :(得分:0)

您的代码似乎是一大竞争条件。只有一个servlet实例用于多个请求。结果,在并发请求时,您当前的代码可能并且将泄漏连接。

在执行并发请求时,它们中的每一个都会创建一个连接并将其分配给相同的实例变量,因此一个或多个连接将丢失并保持打开状态。使用该DBConnection.getConnection / DBConnection.closeConnection意味着您也可能在此泄漏连接。

请停止使用字段来保留connectionstatement,并改用这些局部变量。还可以考虑使用try-with-resources来正确关闭连接,并考虑直接使用DataSource而不是使用DBConnection的(可能是不必要的)抽象。