Java ComboPooledDataSource超出池大小,无法重用

Java ComboPooledDataSource超出池大小,无法重用,java,datasource,limit,connection-pooling,c3p0,Java,Datasource,Limit,Connection Pooling,C3p0,我有以下代码,被其他应用程序(我无法更改)调用以从数据库中读取。 该方法经常在循环中调用,并给DB加剂量。 在DB我可以看到有许多连接打开。。。增加到几百。。。由于负载,数据库崩溃 // Called in a loop private <T> T execute(String query, PostProcessor<T> postProc, PreProcessor preProcs) throws OperationFailedException { try

我有以下代码,被其他应用程序(我无法更改)调用以从数据库中读取。
该方法经常在循环中调用,并给DB加剂量。
在DB我可以看到有许多连接打开。。。增加到几百。。。由于负载,数据库崩溃

// Called in a loop
private <T> T execute(String query, PostProcessor<T> postProc, PreProcessor preProcs) throws OperationFailedException {
    try (Connection conn 
            = Objects.requireNonNull(dataSourceRef.get(), "No Connection").getConnection();
         PreparedStatement smt = conn.prepareStatement(query)) {
        preProc.process(smt);
        return postProc.process(smt.executeQuery());
    } catch (SQLException e) {
        throw new OperationFailedException(e.getMessage(), e);
    }
}
//在循环中调用
private T execute(字符串查询、后处理器后处理程序、预处理器预处理程序)抛出OperationFailedException{
尝试(连接连接)
=Objects.requirennull(dataSourceRef.get(),“无连接”).getConnection();
PreparedStatement smt=conn.prepareStatement(查询)){
预加工工艺(smt);
返回postProc.process(smt.executeQuery());
}捕获(SQLE异常){
抛出新操作FailedException(e.getMessage(),e);
}
}
在…之前初始化源的日期

// class variable
// AtomicReference<PooledDataSource> dataSourceRef = new AtomicReference<PooledDataSource>();

// Init method
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass(config.getConnectionDriver());
cpds.setJdbcUrl(config.getConnectionString());
cpds.setUser(config.getConnectionUser());
cpds.setPassword(config.getConnectionPassword());
// cpds.setMaxPoolSize(10);
dataSourceRef.getAndSet(cpds); 
//类变量
//AtomicReference dataSourceRef=新的AtomicReference();
//初始方法
ComboPooledDataSource cpds=新ComboPooledDataSource();
setDriverClass(config.getConnectionDriver());
setJdbcUrl(config.getConnectionString());
setUser(config.getConnectionUser());
setPassword(config.getConnectionPassword());
//设置最大池大小(10);
数据源getAndSet(cpds);
我的问题是为什么会发生这种情况。
我认为由于池不是每个查询都应该使用新的连接。 此外,通过设置最大池大小,这也不起作用

我还尝试了try-catch-finally构造并在使用后关闭stm和conn。 (正如我在某个地方读到的,在高负载情况下,最终可能会被称为延迟…我认为可能是这样)

但为什么会超出池大小?
如何才能限制和阻止该方法,直到连接在继续之前被再次激活?

在C3P0中的连接轮询期间,您必须考虑一些选项。以下是
application.property
文件:

db.driver: oracle.jdbc.driver.OracleDriver // for Oracle
db.username: YOUR_USER_NAME
db.password: YOUR_USER_PASSWORD
db.url: DATABASE_URL
minPoolSize:5 // number of minimum poolSize
maxPoolSize:100 // number of maximum poolSize
maxIdleTime:5 // In seconds. After that time it will realease the unused connection.
maxStatements:1000
maxStatementsPerConnection:100
maxIdleTimeExcessConnections:10000
这里,
maxIdleTime
是要点。它定义了释放未使用连接的时间。它在第二位

另一个是
minPoolSize
。它定义在空闲模式下它将保持多少连接

另一个是
maxPoolSize
。它定义在加载模式下它将保持的最大连接数

现在,您如何配置
ComboPooledDataSource
?代码如下:

@Bean
    public ComboPooledDataSource dataSource(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        try {
            dataSource.setDriverClass(env.getProperty("db.driver"));
            dataSource.setJdbcUrl(env.getProperty("db.url"));
            dataSource.setUser(env.getProperty("db.username"));
            dataSource.setPassword(env.getProperty("db.password"));
            dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
            dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
            dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
            dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
            dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
            dataSource.setMaxIdleTimeExcessConnections(10000);

        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return dataSource;
    }
有关实施的详细信息,请查看。这里我添加了实际实现

编辑(获取连接)

您可以通过以下方式获得连接:

Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> doSomeStuffWith(connection));
你是如何得到EntityManager的

@PersistenceContext
private EntityManager entityManager;
希望这对你有帮助


> P>在C3P0中的连接轮询期间,你必须考虑一些选项。以下是
application.property
文件:

db.driver: oracle.jdbc.driver.OracleDriver // for Oracle
db.username: YOUR_USER_NAME
db.password: YOUR_USER_PASSWORD
db.url: DATABASE_URL
minPoolSize:5 // number of minimum poolSize
maxPoolSize:100 // number of maximum poolSize
maxIdleTime:5 // In seconds. After that time it will realease the unused connection.
maxStatements:1000
maxStatementsPerConnection:100
maxIdleTimeExcessConnections:10000
这里,
maxIdleTime
是要点。它定义了释放未使用连接的时间。它在第二位

另一个是
minPoolSize
。它定义在空闲模式下它将保持多少连接

另一个是
maxPoolSize
。它定义在加载模式下它将保持的最大连接数

现在,您如何配置
ComboPooledDataSource
?代码如下:

@Bean
    public ComboPooledDataSource dataSource(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        try {
            dataSource.setDriverClass(env.getProperty("db.driver"));
            dataSource.setJdbcUrl(env.getProperty("db.url"));
            dataSource.setUser(env.getProperty("db.username"));
            dataSource.setPassword(env.getProperty("db.password"));
            dataSource.setMinPoolSize(Integer.parseInt(env.getProperty("minPoolSize")));
            dataSource.setMaxPoolSize(Integer.parseInt(env.getProperty("maxPoolSize")));
            dataSource.setMaxIdleTime(Integer.parseInt(env.getProperty("maxIdleTime")));
            dataSource.setMaxStatements(Integer.parseInt(env.getProperty("maxStatements")));
            dataSource.setMaxStatementsPerConnection(Integer.parseInt(env.getProperty("maxStatementsPerConnection")));
            dataSource.setMaxIdleTimeExcessConnections(10000);

        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return dataSource;
    }
有关实施的详细信息,请查看。这里我添加了实际实现

编辑(获取连接)

您可以通过以下方式获得连接:

Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> doSomeStuffWith(connection));
你是如何得到EntityManager的

@PersistenceContext
private EntityManager entityManager;
希望这对你有帮助


谢谢:)

@ScaryWombat:这不是通过try()语法隐式完成的吗?保罗,你是对的,我以为try中只有连接-我应该在发布之前读两遍。@ScaryWombat:这不是通过try()语法隐式完成的吗?保罗,你是对的,我以为只有连接在try中-我应该在发布之前读两遍。