2013-04-26 53 views
0

在ejb 3.0 jboss 6環境中,我有一個名爲DBInterface的bean,注入到許多dao類中以執行sql查詢。 DBInterface bean將數據源作爲字段變量注入。 DBInterface bean中的所有方法都從注入的數據源獲取數據庫連接,並在處理db-calls之後關閉連接。在運行應用程序時,經過一段時間後,我得到的sql異常說不能創建數據庫連接。我正在關閉finally塊中每個方法調用的連接。我在哪裏犯錯誤?我在jboss中使用ejb 3.0。 問候 VEJB 3.0託管bean注入和db連接關閉

public class DBInterface { 
    @Resource(mappedName = "java:ora.ds", type = DataSource.class) 
    private static DataSource dataSource; 
    protected Connection getConnection(){ 
     try { 
     return dataSource.getConnection(); 
     } catch (SQLException e) { 
     e.printstacktrace(); 
     } 
    } 
    public void method1() { 
     Connection connection = null; 
     try { 
       connection = getConnection(); 
       ............... 
       db codes 
       ................. 
     } catch (SQLException e) { 
     logger.error(e); 
     throw new DBException("sql exception ", e); 
     } finally { 
      try { 
        closeResources(rs, statement, connection); 
      } catch (SQLException e) { 
        logger.error(e); 
        throw new DBException("sql exception ", e); 
      } 
     } 
    } 
    public void closeResources(ResultSet rs, Statement st, Connection con) 
     throws SQLException { 
      if (rs != null) { 
      rs.close(); 
      } 
      if (st != null) { 
       st.close(); 
      } 
      if (con != null) { 
      con.close(); 
     } 

     } 
} 
+1

不要注入一個數據源到靜態字段... – 2013-04-26 15:46:34

+0

也一定要關閉單獨的try-catch塊中的資源 – 2013-04-26 15:54:04

+0

是的你是對的,我不再使用靜態數據源。對不起,我在這裏粘貼了舊的測試代碼。 你是什麼意思由單獨的try-catch塊?我有沒有其他的錯誤,我沒有看到這個代碼? – 2013-04-26 18:54:44

回答

1

你應該使用try-catch塊用於關閉任何資源。

if (rs != null) { 
    rs.close(); 
} 
if (st != null) { 
    st.close(); 
} 
if (con != null) { 
    con.close(); 
} 

應改爲:

if (rs != null) { 
    try { 
     rs.close(); 
    } catch (Exception exception) { 
     logger.log("Failed to close ResultSet", exception); 
    } 
} 
if (st != null) { 
    try { 
     st.close(); 
    } catch (Exception exception) { 
     logger.log("Failed to close Statement", exception); 
    } 
} 
if (con != null) { 
    try { 
     con.close(); 
    } catch (Exception exception) { 
     logger.log("Failed to close Connection", exception); 
    } 
} 

這可重構的東西,很容易使用AbstractDao的類閱讀:

public class DAOException extends RuntimeException { 
    public DAOException(Throwable cause) { 
     super(cause); 
    } 
} 

public abstract class AbstractDAO { 
    private static Logger logger = ...; 
    private DataSource dataSource; 

    protected void setDataSource(DataSource dataSource) { 
     this.dataSource = dataSource; 
    } 

    public Connection getConnection() { 
     try { 
      return dataSource.getConnection(); 
     } catch (SQLException exception) { 
      // There's nothing we can do 
      throw new DAOException(exception); 
     } 
    } 

    public void close(Connection connection) { 
     try { 
      connection.close(); 
     } catch (Exception exception) { 
      // Log the exception 
      logger.log("Failed to close Connection", exception); 
     } 
    } 

    public void close(Statement statement) { 
     try { 
      statement.close(); 
     } catch (Exception exception) { 
      // Log the exception 
      logger.log("Failed to close Statement", exception); 
     } 
    } 

    public void close(ResultSet resultSet) { 
     try { 
      resultSet.close(); 
     } catch (Exception exception) { 
      // Log the exception 
      logger.log("Failed to close ResultSet", exception); 
     } 
    } 
} 

public class MyDAO extends AbstractDAO { 
    @Override 
    @Resource("jdbc/myDS") 
    protected void setDataSource(DataSource dataSource) { 
     super.setDataSource(dataSource); 
    } 

    public void insert(MyObject myObject) { 
     Connection connection = getConnection(); 
     try { 
      PreparedStatement query = connection.createPreparedStatement("INSERT INTO MYOBJECT (ID, VALUE) VALUES (?, ?)"); 
      try { 
       query.setLong(1, myObject.getID()); 
       query.setString(2, myObject.getValue()); 
       if (query.executeUpdate() != 1) { 
        throw new DAOException("ExecuteUpdate did not return expected result"); 
       } 
      } finally { 
       close(query); 
      } 
     } catch (SQLException exception) { 
      // There's nothing we can do 
      throw new DAOException(exception); 
     } finally { 
      close(connection); 
     } 
    } 
} 

什麼我不知道的是,爲什麼AREN你使用JPA嗎?我會考慮將JDBC僅用於無法從緩存中受益的性能關鍵應用程序。

+0

我不會使用JPA的原因是由於第三方定期更新的數據併發症。所以我需要在幾個JPA幫助我的地方使用查詢。 – 2013-04-27 10:13:26

+0

每當表結構發生變化時,我都會使用視圖而不是更新sql-queries。 – 2013-04-27 10:42:07