#spring-batch
Вопрос:
У меня следующая ошибка с 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;
}
Я использовал «Целое число.MAX_VALUE» для corePoolSize, maxPoolSize и емкости очереди (вместо 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();
Ответ №1:
Вы исчерпываете пул подключений к базе данных, потому что не закрываете соединения, чтобы вернуть их обратно в пул. Вы звоните только close
по CallableStatement
телефону . Попробуйте что-нибудь в этом роде…
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
соединений.
Комментарии:
1. Большое вам спасибо, вы правы. Я решил свою проблему. Хорошего вам конца дня.
Ответ №2:
Здесь есть два ключевых параметра: размер пула рабочих потоков и размер пула соединений базы данных.
Если каждый поток запрашивает подключение к базе данных, и у вас больше работников, чем доступных подключений, то в какой-то момент рабочие потоки будут ждать, пока подключения станут доступными. Это ожидание может затянуться, если соединения не будут освобождены до заданного значения тайм-аута.
Поэтому вам нужно убедиться, что у вас достаточно соединений для рабочих потоков, или увеличить время ожидания в пуле соединений.