简体   繁体   中英

How to properly close MySql database connection

In my web application I have separate classes DataAccess.java and DBUtils.java.

I have following code in DBUtils.jva

public static PreparedStatement getPreparedStatement(String sql) throws ClassNotFoundException, SQLException{
    PreparedStatement ps = null;
    Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost:3306/company";
    String user = "root";
    String pass = "root";

    Connection con = DriverManager.getConnection(url, user, pass);
    ps = con.prepareStatement(sql);       

    return ps;

I have following code in DataAccess.java class

public static List<Company> getAllCompanies(){
    List<Company> ls = new LinkedList<>();

    try {
        String sql = "select * from company";
        ResultSet rs = DBUtils.getPreparedStatement(sql).executeQuery();            
        while (rs.next()){
            Company cp = new Company (rs.getInt(1), rs.getString(2), rs.getInt(3),rs.getTimestamp(9));
            ls.add(cp);
        }
        rs.close();            
    } catch (ClassNotFoundException | SQLException ex) {
        Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
    }

    return ls;
}

And I am calling getAllCompanies function from a different servlet. I don't know how to properly close database connection as it is opened in one class and called from another class. My web application keeps crashing due to too many open connections to database, the error says,

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"

Could someone please advise me on how to properly close database connection in this case.

you are only closing the resultset

but you are not closing the connection.

in a finally block please do

con.close()

refer this for more info : Closing Database Connections in Java

Basically, you are NOT closing the database connection objects which is creating the connection leaks. So you need to modify your DBUtil method to getConnection() as shown below.

Always close the resources ( connection , preparedstatement and resultset objects) in the finally block as shown below, otherwise it will create the connection leaks and very soon you will run out of connections.

DBUtil getConnection():

public static Connection getConnection() throws ClassNotFoundException, SQLException{
    PreparedStatement ps = null;
    Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost:3306/company";
    String user = "root";
    String pass = "root";

    Connection con = DriverManager.getConnection(url, user, pass);
    return con;
}

getAllCompanies() code:

public static List<Company> getAllCompanies(){
    List<Company> ls = new LinkedList<>();
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    Connection conn = null;
    try {
        String sql = "select * from company";
         conn = DBUtils.getConnection();
         pstmt = conn.prepareStatement(sql);       
        rs = pstmt.executeQuery();            
        while (rs.next()){
            Company cp = new Company (rs.getInt(1), rs.getString(2), rs.getInt(3),rs.getTimestamp(9));
            ls.add(cp);
        }

    } catch (ClassNotFoundException | SQLException ex) {
        Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        if(rs != null) {
             rs.close();
        }
        if(pstmt !=null) {
           pstmt.close();
        } 
        if(conn != null) {
           conn.close();
        }
    }
    return ls;
}

Also, I strongly suggest you to create methods like closeConnection() , closeResultSet() , closePreparedStatement() in your DBUtil class in order to avoid the boilerplate code in all methods.

I have following code now in DBUtils.java class i have following methods

public static void closeResultSet(ResultSet rs) throws ClassNotFoundException, SQLException {
    if(rs != null) {
        try {
            rs.close();
        } catch (SQLException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}   

public static void closePreparedStatement(PreparedStatement ps) throws ClassNotFoundException, SQLException {
    if(ps != null) {
        try {
            ps.close();
        } catch (SQLException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}  

public static void closeConnection(Connection conn) throws ClassNotFoundException, SQLException {
    if(conn != null) {
        try {
            conn.close();
        } catch (SQLException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}  

And in DataAccess.java class I have,

public static List<Company> getAllCompanies(){
    List<Company> ls = new LinkedList<>();
    ResultSet rs = null;
    PreparedStatement ps = null;        
    Connection conn = null;
    try {
        String sql = "select * from company";
        conn = DBUtils.getConnection();
        ps = conn.prepareStatement(sql);
        rs = ps.executeQuery();
        while (rs.next()){
            Company cp = new Company (rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getTimestamp(9));
            ls.add(cp);
        }
    } catch (ClassNotFoundException | SQLException ex) {
        Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
    }finally {
        DBUtils.closeResultSet(rs);
        DBUtils.closePreparedStatement(ps);
        DBUtils.closeConnection(conn);
    }

I have not compiled it yet but I think it should be fine. Thanks again for the help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM