У меня есть RestController, который вызывает метод из службы. Метод добавляет пользователя в базу данных PostresSQL, которая имеет максимум 20 соединений.Spring Transactional метод, который возвращает CompletableFuture
@RestController
public class Controller {
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String addUser(@RequestBody UserInfo userInfo) {
Future<String> completableFuture = userService.addUser(userInfo);
String answer = voidCompletableFuture.get();
return answer;
}
}
Метод в сервисе прокомментирован Spring транзакционного, после того, как сохраняющийся метод возвращает данные CompletableFuture, внутри него некоторой длительная эксплуатации. Я вызываю метод «/ user» одновременно из нескольких потоков (около 100).
@Transactional
public Future<String> addUser(UserInfo userInfo) {
userDao.persist(userInfo);
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000);
return "Result";
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Error";
});
}
Если строка кода «voidCompletableFuture.get()», который блокирует текущий поток, называется тогда только 20 одновременного запроса работает и добавления данных в базу данных по количеству максимальных соединений. Существует исключение в других нитей:
Caused by: java.sql.SQLTransientConnectionException: Connection is not available, request timed out after 30000ms.
Если удалить эту строку кода, то каждый запрос работает и добавляет данные в базу данных, как и ожидалось. Я думаю, что это потому, что Transaction не завершилась после завершения метода «public Future addUser (UserInfo userInfo)», если я вызову future.get() после. Возможно, кто-то знает, почему Spring и CompletableFuture работают таким образом или, может быть, есть еще один ответ? Почему блокирование CompletableFuture влияет на конец транзакции другим способом? Почему метод не завершает текущую транзакцию и не освобождает соединение, если существует метод внутри блока.
случайно, это было бы возможно, что ваша транзакция уже запущена, когда вы звоните 'AddUser()', и не совершала перед вызовом '' получить) метод (? –
@DidierL Я просмотрел журнал транзакций, транзакции начинаются в 'addUser()', а затем только несколько из них заканчиваются перед вызовом метода get(). Затем транзакции прекращают завершение (log 'TransactionInterceptor: 485: Завершение транзакции') за время, когда' get() 'блокирует запрос. И тогда число соединений становится более чем максимальным в пуле соединений в dataSource, а затем происходит это исключение. 'Caused by: java.sql.SQLTransientConnectionException: соединение недоступно'. Не знаю, почему соединения прекращаются. –