Я думаю, что мог заметить тупиковую ситуацию, пытаясь одновременно сохранить объекты с помощью аннотации @Async.
Я использовал такой компонент, как
@Component
public class AsyncInserter{
@Autowired
private PersonRepository repository;
@Async
@Transactional
public CompletableFuture<Boolean> insert(List<Person> persons){
repository.saveAll(persons);
repository.flush();
return CompletableFuture.completedFuture(Boolean.TRUE);
}
Я звоню из сервисного уровня, который определяется как
@Составная часть
открытый класс PersonServiceImpl {
@Autowired
private AsyncInserter asyncInserter;
@Transactional
public void performDBOperation(List<Person> persons){
deletePersons(/** some criteria */);
List<List<Person>> subPersonList = Lists.partition(persons, 100);
subPersonList.forEach(list->{ statuses.add(asyncInserter.insert(list));});
}
Как вы заметили, у меня есть команды удаления и вставки (по совместительству), которые я хотел полностью атомарные.
Но я заметил, что это удаление, и несколько вставок отправляются, но никогда не фиксируются.
Я думаю, что есть какая-то блокировка, которая мешает, и я могу изолировать ее при работе в параллельных потоках. В соответствии с https://dzone.com/articles/spring-and-threads-transactions, создается впечатление, что при создании нового потока внешняя транзакция не распространяется на вновь созданный поток, и создается новая транзакция.
У этой конструкции, похоже, есть недостаток. Нужно ли мне удалять перед отправкой для вставок? Но как мне добиться атомарной операции, если одна из вставок дает сбой
Я изменил код для запуска удаления и вставки в одном потоке, и он работает, что в любом случае ожидается. Но то, что я заметил, это то, что после вставки записей требуется больше времени для фиксации. Обычно, 12 секунд больше, чтобы зафиксировать 10K записей. Какие огромные накладные расходы? Есть ли способ улучшить это?
Кстати, я использую пул Hikari Connection.
Спасибо