Datasource in jdbc connection pooling not returning connection [duplicate]

眉间皱痕 提交于 2019-12-20 06:23:43

问题


I have a jsp web application. I'm using jdbc connection pooling to use mysql database located at the server side. My web application hangs sometimes, when i checked debugging i found that it hangs at ds.getConnection(); It does not return any exception/error. Browser will be simply in loading state. I have included my DBConnection class which i use to create dadasource and getconnection from datasource.I'm calling getConnection(); method to get connection from pool. I have called closeConnection(); method in all jsp finally block to close connection. So i assume that the connection will be returned to pool once i close the connection

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>

Example servlet to show how i use the connection

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";
    }
}

回答1:


You forgot to close the connection

Use a finally statement to close a pooled connection. The following finally block would appear after the try/catch block that applies to the code in which the pooled connection was used:

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();
 }

Your datasource reached the maximum connection defined.




回答2:


Your code seems to be one big race condition. Only one servlet instance is used for multiple requests. As a result, on concurrent requests, your current code can and will leak connections.

When concurrent requests are executed, each of them will create a connection and assign it to the same instance variable, so one or more connections will be lost and remain open. The use of that DBConnection.getConnection/DBConnection.closeConnection suggests that you are potentially leaking connections there as well.

Please stop using fields to keep your connection and statement, and make these local variables instead. Also consider using try-with-resources to properly close connections, and consider using a DataSource directly instead of using that (probably unnecessary) abstraction of DBConnection.



来源:https://stackoverflow.com/questions/54234422/datasource-in-jdbc-connection-pooling-not-returning-connection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!