Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Tomcat连接池&;空闲连接_Java_Postgresql_Tomcat_Connection Pooling - Fatal编程技术网

Java Tomcat连接池&;空闲连接

Java Tomcat连接池&;空闲连接,java,postgresql,tomcat,connection-pooling,Java,Postgresql,Tomcat,Connection Pooling,我们正在开发一个网站使用 雄猫7 JDBC PostgreSQL 9.2 我们遇到了一些连接泄漏,并认为我们已经纠正了它们(数据库不再停止响应),但连接池的行为似乎仍然存在泄漏,因为我们的空闲连接数大于context.xml中的maxIdle集。我想确定这个问题已经解决了 出于测试目的,我使用以下context.xml: <Resource auth="Container" name="jdbc/postgres" factory="org.apache.to

我们正在开发一个网站使用

  • 雄猫7
  • JDBC
  • PostgreSQL 9.2
我们遇到了一些连接泄漏,并认为我们已经纠正了它们(数据库不再停止响应),但连接池的行为似乎仍然存在泄漏,因为我们的空闲连接数大于context.xml中的maxIdle集。我想确定这个问题已经解决了

出于测试目的,我使用以下context.xml:

 <Resource
    auth="Container"
    name="jdbc/postgres"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
    type="javax.sql.DataSource"

    username="admin"
    password="..."

    driverClassName="org.postgresql.Driver"
    url="jdbc:postgresql://127.0.0.1:5432/..."
    initialSize="1"
    maxActive="50"
    minIdle="0"
    maxIdle="3"
    maxWait="-1"
    minEvictableIdleTimeMillis="1000"
    timeBetweenEvictionRunsMillis="1000"
    />

DAO抽象类:

public abstract class DAO implements java.lang.AutoCloseable {

    // Private attributes :
    private Connection _connection;

    // Constructors :
    public DAO() {

        try { _connection = PostgreSQLConnectionProvider.getConnection(); }
        catch (NamingException | SQLException ex) { 
            Logger.getLogger(DAO.class.getName()).log(Level.SEVERE, null, ex); 
        }
    }

    // Getters :
    public Connection getConnection() { return _connection; }

    // Closeable :
    @Override
    public void close() throws SQLException {

        if(!_connection.getAutoCommit()) {

            _connection.rollback();
            _connection.setAutoCommit(true);
        }

        _connection.close();
    }
}

UserDAO,一个小的DAO子类(我们有几个DAO子类来请求数据库):


DAO子类使用示例:

try(UserDAO dao = new UserDAO()) {

    try {

        User user = dao.getUserWithId(52);
    }
    catch (SQLException ex) {

        // Handle exeption during getUserWithId
    }
}
catch (SQLException ex) {

    // Handle exeption during dao.close()
}

从代码看,连接似乎是在DAO的生命周期内捕获的,而不是语句的生命周期,这是通常的期望。通常,您会在即将执行语句时从池中获取一个连接,并在执行完毕后调用close(),以便将其返回到池中

此外,在finally子句中,
rs.close()
ps.close()
都会抛出异常,导致错过对准备语句的最后一次调用


在Java7中,您还可以使用一条语句来关闭准备好的语句和连接。根据规范,当语句关闭时,驱动程序应该为您关闭结果。

尝试使用tomcat的连接池实现-它的功能更丰富,有很好的文档,谢谢,但这已经是我正在做的事情了(您可以看到我在context.xml中使用的参数).我看不到主要部分-
工厂
属性和相应的类名OOPS您是对的,此属性是必需的,我没有看到它。但是添加它并没有改变任何事情(我的参数已经被考虑在内:initialSize始终受到尊重)。使用RemoveBandoned和RemoveBandoneTimeout可以使空闲连接在每次RemoveBandoneTimeout都消失,所以我想我们仍然存在连接泄漏:/。感谢您的回答。是的,连接在DAO的整个生命周期中都被占用,但是几行之后DAO就关闭了,我不认为这是个问题,不是吗?对于可以抛出异常的close(),您是对的,我将它们包装在一个try-catch中(我更喜欢自己调用rs.close(),而不是依赖于驱动程序的实现)。我要到下周才能测试,我会告诉你close()包装是否改变了什么。如果你为每次调用getUserWithId()实例化DAO,那么是的,应该可以。
public class UserDAO extends DAO {

    public User getUserWithId(int id) throws SQLException {

        PreparedStatement ps = null;
        ResultSet rs = null;

        User user = null;

        try {

            String sql = "select * from \"USER\" where id_user = ?;";

            ps = getConnection().prepareStatement(sql);
            ps.setInt(1, id);

            rs = ps.executeQuery();
            rs.next();

            String login = rs.getString("login");
            String password = rs.getString("password");
            String firstName = rs.getString("first_name");
            String lastName = rs.getString("last_name");
            String email = rs.getString("email");

            user = new User(id, login, password, firstName, lastName, email);
        }
        finally {

            if(rs != null) rs.close();
            if(ps != null) ps.close();
        }

        return user;
    }
}
try(UserDAO dao = new UserDAO()) {

    try {

        User user = dao.getUserWithId(52);
    }
    catch (SQLException ex) {

        // Handle exeption during getUserWithId
    }
}
catch (SQLException ex) {

    // Handle exeption during dao.close()
}