我有以下错误与SpringBatch:
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
考虑到我有很多文件要加载,我认为错误是因为我的TaskExecutor:
@Bean
public TaskExecutor MyTE() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(64);
executor.setMaxPoolSize(64);
executor.setQueueCapacity(64);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("MyTE-");
return executor;
}
我使用了"Integer.MAX_VALUE"对于CorePoolSize, MaxPoolSize和QueueCapacity(而不是64),但错误都发生相同。
编辑:最终,我的问题的原因似乎是对存储过程的调用在beforeJob。实际上,当我注释下面的代码时,它工作了。@Override
public void beforeJob(JobExecution jobExecution) {
CallableStatement cs=null;
cs=MyDataSource.getConnection().prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
然而,我想做这个调用,我不明白为什么它会产生一个问题。与cs.close();
的联系似乎很紧密
有什么问题?
致意。
解决方案:
Connection con = null;
CallableStatement cs = null;
con=MyDataSource.getConnection();
cs=con.prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
con.close();
正在耗尽数据库连接池,因为您没有关闭连接以将它们释放回池中。你只在CallableStatement
上调用close
。试试这样做…
try (Connection conn = MyDataSource.getConnection()) {
CallableStatement cs= conn.prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
}
这将自动关闭Connection
对象并将其释放回DataSource
连接池。
这里有两个关键参数:工作线程池的大小和数据库连接池的大小。
如果每个线程请求一个数据库连接,并且工作线程多于可用连接,那么在某些时候工作线程将等待连接变得可用。如果在配置的超时值之前没有释放连接,则此等待可能超时。
所以你需要确保你的工作线程有足够的连接,或者增加连接池中的超时时间。