2011-06-08 70 views
3

我正在尝试在Java中为我的Web应用程序使用池连接。我使用的是Oracle数据库,这里是我的代码:我是否正确地关闭了此Oracle池连接?

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

我在Eclipse这样做的,我有一个警告,pooledSource.close()已被弃用。我从来没有使用过连接池,我只是想确保我做的一切都正确。有没有更好的方法来关闭Oracle池化资源?

回答

6

不推荐使用的方法意味着不应使用此方法。在未来的版本中,可以完全清除close()方法。我建议删除pooledSource.close()

此外,我建议不要有一个ConnectionDataSource的静态实例,因为您需要请求连接,并且不会在整个应用程序中保持活动状态。请务必首先关闭ResultSet,然后再将Connection保证的关闭,方法是将其添加到finally区块中。

+0

因此,我不需要显式关闭池连接,它是为我处理的?我想这可能是这种情况,但我想100%肯定,所以我不放弃连接而不是关闭连接。 – 2011-06-08 14:48:40

+1

您不需要关闭连接池。如果从池中获得连接,则“连接”属于连接池,因此关闭连接会将其自动返回到池中。 – 2011-06-08 14:50:38

+0

谢谢你的详细解释。 – 2011-06-08 14:52:19

1
  1. 连接必须关闭才能返回到池中。
  2. 始终在finally块中关闭连接。
  3. 永远不要把连接引用当作类成员 - 这是容易出错和糟糕的设计。尽可能晚地连接并尽快释放连接。把这样的东西当作集体成员是没有意义的。
  4. 关闭使用它们的连接。你的代码在这里再次出错。如果您忘记拨打closeDatabase(),说明您正在泄漏连接。

注意: 不要混淆关闭connection这里关闭connection pool

因为在这里要求是正确和良好的连接处理一些代码:

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

我使用的连接,方法的参数,以便能够调用许多中一个数据块的交易这样的方法。但是您始终可以将null作为Connection的第一个参数,并且该方法可以从您的池中获取连接。

当您在“DB-Method”中调用另一个“DB-Method”时,您只需提供与底层方法的连接 - 以便在一个事务中拥有所有内容。

正如您所看到的,正确的JDBC代码会生成许多样板代码。在第一步中,你可以通过实现像PersistenceUtils这样的实用程序类来减少它,它提供静态的空安全方法,如提交(Connection),回滚(Connection),getConnection(连接),关闭(Connection)... 因为你摆脱所有的空检查,你也可以包括日志记录或其他东西。

+0

对于第一点,这是如何实现的? – 2011-06-08 15:16:22

+0

@The Elite Gentleman在连接对象上调用close()。也许它也会在垃圾收集时(我不知道)检查是否返回池中,但是因为尽快将其返回池很重要,所以必须自己调用它。按照步骤2以正确的方式执行此操作 - 始终在finally块中关闭这些资源。 – 2011-06-08 15:28:48

+0

感谢您的帮助,我已经应用了您在此提供的建议。 – 2011-06-08 16:59:38