org.apache.tomcat.dbcp.dbcp.SQLNestedException:无法获取连接,池错误等待空闲对象超时

org.apache.tomcat.dbcp.dbcp.SQLNestedException:无法获取连接,池错误等待空闲对象超时,exception,jakarta-ee,jsf-2,tomcat7,mysql-workbench,Exception,Jakarta Ee,Jsf 2,Tomcat7,Mysql Workbench,我使用的是Tomcat 7、MySql Workbench 5.2.27和JSF 2.0,这个异常来自我的web pageTrip Record.xhtml的ManagedBeanTripTableBean.java。在浏览其他网页后,每当我单击以转到Trip Record.xhtml时,它就会出现。请原谅我可怕的密码 TripTableBean.java } 更新2: 当ManagedBeanTripTableBean.java的作用域是ViewScope时会发生此异常,当我将其更改为Sess

我使用的是Tomcat 7、MySql Workbench 5.2.27和JSF 2.0,这个异常来自我的web pageTrip Record.xhtml的ManagedBeanTripTableBean.java。在浏览其他网页后,每当我单击以转到Trip Record.xhtml时,它就会出现。请原谅我可怕的密码

TripTableBean.java

}

更新2:
当ManagedBeanTripTableBean.java的作用域是ViewScope时会发生此异常,当我将其更改为SessionScoped时不会发生此异常。但是,如果是会话范围,我需要找到一种方法,在每次访问此网页时终止会话并重新创建一个新会话。如果不是,则此网页上的dataTable不会从数据库加载更新的更改。

您有什么连接池设置可以在DBController中发布什么? 提示:db.terminate应该位于finally{}块中,可能是因为您在异常情况下丢失了连接

更新: 发布一些可能会对您有所帮助的修改,但为了维护起见,一定要清理代码。查找已进行更改的注释

public class DBController {
private DataSource ds;
private Connection con;// NEW CHANGE

public void setUp() throws NamingException{
    //connect to database
    Context ctx = new InitialContext();
    ds = (DataSource)ctx.lookup("java:comp/env/jdbc/it2299");
    con = ds.getConnection(); // NEW CHANGE
}

public ResultSet readRequest(String dbQuery){
    ResultSet rs=null;
    try{
        //REMOVED CODE FROM HERE
        Statement stmt = con.createStatement();
        rs = stmt.executeQuery(dbQuery);
    }
    catch(Exception e){e.printStackTrace();}
    return rs;
}

public int updateRequest(String dbQuery){
    int count=0;
    try{
        //REMOVED CODE FROM HERE
        Statement stmt = con.createStatement();
        count=stmt.executeUpdate(dbQuery);
    }
    catch(Exception e){e.printStackTrace();}
    return count;
}

public void terminate(){
    try {con.close();}
    catch(Exception e){e.printStackTrace();}
}
}
除此之外,我无法改进代码,但我建议大家看看@BalusC建议的一些网上最佳实践。
记住:完成后关闭连接对象。

您的连接池设置是什么?您可以在DBController中发布什么? 提示:db.terminate应该位于finally{}块中,可能是因为您在异常情况下丢失了连接

更新: 发布一些可能会对您有所帮助的修改,但为了维护起见,一定要清理代码。查找已进行更改的注释

public class DBController {
private DataSource ds;
private Connection con;// NEW CHANGE

public void setUp() throws NamingException{
    //connect to database
    Context ctx = new InitialContext();
    ds = (DataSource)ctx.lookup("java:comp/env/jdbc/it2299");
    con = ds.getConnection(); // NEW CHANGE
}

public ResultSet readRequest(String dbQuery){
    ResultSet rs=null;
    try{
        //REMOVED CODE FROM HERE
        Statement stmt = con.createStatement();
        rs = stmt.executeQuery(dbQuery);
    }
    catch(Exception e){e.printStackTrace();}
    return rs;
}

public int updateRequest(String dbQuery){
    int count=0;
    try{
        //REMOVED CODE FROM HERE
        Statement stmt = con.createStatement();
        count=stmt.executeUpdate(dbQuery);
    }
    catch(Exception e){e.printStackTrace();}
    return count;
}

public void terminate(){
    try {con.close();}
    catch(Exception e){e.printStackTrace();}
}
}
除此之外,我无法改进代码,但我建议大家看看@BalusC建议的一些网上最佳实践。
请记住:完成后关闭连接对象。

正如您所暗示的,您的代码非常糟糕。您需要确保在try-finally块中在尽可能短的范围内获取并关闭所有JDBC资源。重写代码,使其遵循以下标准JDBC习惯用法:

public List<Entity> list() throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    List<Entity> entities = new ArrayList<Entity>();

    try {
        connection = Database.getConnection();
        statement = connection.prepareStatement("SELECT id, foo, bar FROM entity");
        resultSet = statement.executeQuery();

        while (resultSet.next()) {
            Entity entity = new Entity();
            entity.setId(resultSet.getLong("id"));
            entity.setFoo(resultSet.getString("foo"));
            entity.setBar(resultSet.getString("bar"));
            entities.add(entity);
        }
    } finally {
        if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
        if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
        if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
    }

    return entities;
}
另见:
正如你自己暗示的,你的代码很糟糕。您需要确保在try-finally块中在尽可能短的范围内获取并关闭所有JDBC资源。重写代码,使其遵循以下标准JDBC习惯用法:

public List<Entity> list() throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    List<Entity> entities = new ArrayList<Entity>();

    try {
        connection = Database.getConnection();
        statement = connection.prepareStatement("SELECT id, foo, bar FROM entity");
        resultSet = statement.executeQuery();

        while (resultSet.next()) {
            Entity entity = new Entity();
            entity.setId(resultSet.getLong("id"));
            entity.setFoo(resultSet.getString("foo"));
            entity.setBar(resultSet.getString("bar"));
            entities.add(entity);
        }
    } finally {
        if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
        if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
        if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
    }

    return entities;
}
另见:
谢谢你的帮助,我将尝试添加最后{}块。我已经在帖子中添加了我的DBController。更新:异常仍然发生。我尝试用另一个网页交替打开此网页,当我第6次单击转到此网页时出现异常。最后{}我的意思是通过应用程序而不仅仅是上面的代码:。我还注意到您的readRequest方法打开了一个新的连接,它在循环中使用,您可以使用相同的连接来创建语句,这样它也可能在事务中有所帮助。您可能需要一些代码中的where。嗯,使用相同的连接?您的意思是对所有dbQuery使用相同的结果集?或者为每个结果集创建一个新的DBController?我迷路了=\这种方法仍然很糟糕。您需要重写更多的代码。感谢您的帮助,我将尝试添加finally{}块。我已经在帖子中添加了我的DBController。更新:异常仍然发生。我尝试用另一个网页交替打开此网页,当我第6次单击转到此网页时出现异常。最后{}我的意思是通过应用程序而不仅仅是上面的代码:。我还注意到您的readRequest方法打开了一个新的连接,它在循环中使用,您可以使用相同的连接来创建语句,这样它也可能在事务中有所帮助。您可能需要一些代码中的where。嗯,使用相同的连接?您的意思是对所有dbQuery使用相同的结果集?或者为每个结果集创建一个新的DBController?我迷路了=\这种方法仍然很糟糕。你需要重写更多的代码。也谢谢你的帮助,我目前正试图遵循上述格式。呃,我可以知道那个数据库类中有什么吗?第7行导入=\不可用,在仍然执行while循环第一次查询的情况下,如何执行while循环第二次查询?关于数据库类,请参阅链接以获取示例。它应该只创建并返回连接,而不是将该连接作为该类的实例变量!。至于第二个查询,请学习SQL JOIN子句,这样您只会得到一个查询,它会精确地返回您所需的数据。也感谢您的帮助,我目前正在尝试使用上述格式。呃,我可以知道那个数据库类中有什么吗?第7行导入=\不可用,在仍然执行while循环第一次查询的情况下,如何执行while循环第二次查询?关于数据库类,请参阅链接以获取示例。它应该只创建并返回连接,而不是将该连接作为该类的实例变量!。至于第二个查询,请学习SQL JOIN子句,以便最终得到on ly 1查询,它精确地返回您需要的数据。
public List<Entity> list() throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    List<Entity> entities = new ArrayList<Entity>();

    try {
        connection = Database.getConnection();
        statement = connection.prepareStatement("SELECT id, foo, bar FROM entity");
        resultSet = statement.executeQuery();

        while (resultSet.next()) {
            Entity entity = new Entity();
            entity.setId(resultSet.getLong("id"));
            entity.setFoo(resultSet.getString("foo"));
            entity.setBar(resultSet.getString("bar"));
            entities.add(entity);
        }
    } finally {
        if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
        if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
        if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
    }

    return entities;
}