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中-我应该在发布之前读两遍。