/**
  * Close and free all {@link PreparedStatement}s from my pool, and close my underlying connection.
  */
 public synchronized void close() throws SQLException {
   if (null != _pstmtPool) {
     KeyedObjectPool oldpool = _pstmtPool;
     _pstmtPool = null;
     try {
       oldpool.close();
     } catch (RuntimeException e) {
       throw e;
     } catch (SQLException e) {
       throw e;
     } catch (Exception e) {
       throw new SQLNestedException("Cannot close connection", e);
     }
   }
   getInnermostDelegate().close();
 }
 /**
  * Create or obtain a {@link PreparedStatement} from my pool.
  *
  * @return a {@link PoolablePreparedStatement}
  */
 public synchronized PreparedStatement prepareStatement(String sql) throws SQLException {
   try {
     return (PreparedStatement) (_pstmtPool.borrowObject(createKey(sql)));
   } catch (NoSuchElementException e) {
     throw new SQLNestedException("MaxOpenPreparedStatements limit reached", e);
   } catch (RuntimeException e) {
     throw e;
   } catch (Exception e) {
     throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
   }
 }
 public String toString() {
   return "PoolingConnection: " + _pstmtPool.toString();
 }