2013-04-26 62 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