简体   繁体   中英

Am I closing this Oracle pooled connection correctly?

I am attempting to use a pooled connection for my web application in Java. I am using an Oracle database and here is my code:

public class DatabaseHandler
{

    static private Connection m_database = null;

    static private OracleConnectionPoolDataSource pooledSource = null;

    /**
     * Attempts to open an Oracle database located at the specified serverName and port.
     * @param serverName Address of the server.
     * @param portNumber Port to connect to.
     * @param sid SID of the server.
     * @param userName Username to login with.
     * @param password Password to login with.
     * @throws WebApplicationException with response code 500 Internal Server Error.
     */
    static public void openDatabase(String userName, String password,String serverName,int portNumber, String sid)
    throws WebApplicationException
    {
        try
        {
            // Load the JDBC driver
            String driverName = "oracle.jdbc.driver.OracleDriver";
            Class.forName(driverName);

            // Create a connection to the database
            String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber + ":" + sid;
            pooledSource = new OracleConnectionPoolDataSource();

            pooledSource.setUser(userName);
            pooledSource.setURL(url);
            pooledSource.setPassword(password);
            m_database = pooledSource.getConnection();

        }
        catch (ClassNotFoundException e) 
        {
            // Could not find the database driver
            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
        }
        catch (SQLException e) 
        {
            // Could not connect to the database
            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
        }
    }


    /**
     * Attempts to execute the specified SQL query.
     * @throws WebApplicationException with a response code of Bad Request
     * if the query is invalid SQL.
     */
    static public ResultSet makeQuery(String query) throws WebApplicationException
    {
        ResultSet rs = null;
        if (m_database != null)
        {
            try 
            {
                Statement stmt = m_database.createStatement();
                rs = stmt.executeQuery(query);
            }
            catch (SQLException e)
            {
                // invalid query
                System.out.println(query);
                throw new WebApplicationException(Response.Status.BAD_REQUEST);
            }
        }        
        return rs;
    }

    /**
     * Attempts to close the database. 
     * @throws WebApplicationException with a response code of  500 Server error
     */
    static public void closeDatbase() throws WebApplicationException
    {
        try
        {
            m_database.close();
            pooledSource.close();
        }
        catch(SQLException e)
        {
            throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
        }
    }
}

I am doing this in Eclipse and I have a warning that pooledSource.close() is deprecated. I have never used a pooled connection before and I just want to be sure that I am doing everything correctly. Is there a better way to close an Oracle pooled resource?

A deprecated method means that this method shouldn't be used. In future releases, the close() method can be purged entirely. I suggest removing pooledSource.close() .

Also, I would suggest not to have a static instance of a Connection and DataSource as you require a connection on request and not keep it alive throughout the application. Always close a ResultSet first and then a Connection and guarantee the closure by adding them in a finally block.

  1. The connection must be closed to be returned to the pool.
  2. Always close your connection in a finally-block.
  3. Never hold connection references as a class member - this is error prone and bad design. Connections should be aquired as late as possible and released as soon as possible. It does not make sense to hold something like that as class member.
  4. Close connections where they are used. Your code is error prone again here. If you forget to call closeDatabase() you're leaking connections.

Attention: Do not jumble closing the connection and closing the connection pool here.

Because it was requested here's some code for correct and good connection handling:

public void doSomethingWithDb(Connection con, ...) {
    boolean release = (con == null);

    try {
        con = PersistenceUtils.getConnection(con); //static helper return a new conenction from pool when provided con==null otherwise simply returns the given con

        //do something

        if(release) {
            con.commit();
        }
    }
    catch(SQLException e) {
        //handle errors, i.e. calling con.rollback() but be sure to check for con!=null before. Again maybe null-safe static helper method here.
    }
    finally {
        if(release && con!=null){
            con.close();
        }
    }
}

I am using Connection as method parameter in order to be able to call many of such methods in one db transaction. But you can always put null as first argument for Connection and the method get a connection from pool for you.

When you call another "DB-Method" inside a "DB-Method" you just provide your connection to the underlying method - so you have everything in one transaction then.

As you see correct JDBC code produces much boilerplate code. In the first step you can reduce it by implementing a Utility-Class like PersistenceUtils which provides static null-safe methods like commit(Connection), rollback(Connection), getConnection(Connection), close(Connection)... With that you get rid of all null-checks and you can include logging or something else there, too.

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