Объекты не сохраняются в БД при использовании асинхронного выполнения Spring - PullRequest
1 голос
/ 03 мая 2019

Мне нужно запустить асинхронное задание, которое импортирует данные (считанные из файла) в БД MySQL.Я использую Spring Data's CrudRepository.Проблема в том, что, несмотря на вызов метода сохранения, в БД не сохраняется никаких данных.

Честно говоря, я не знаю, как начать решать эту проблему.Я не вижу каких-либо ошибок или предупреждений в своих журналах, и при поиске в Google я нашел только следующее предложение:

Spring JPA: данные не сохраняются в базе данных при обработке из асинхронного метода

Однако я уже применил его, и мой код все еще не работает.Запуская код синхронно (удаляя аннотацию @Async), все работает как положено.

Фрагмент моего кода:

AsyncImportService.java

@Service
public class AsyncImportService {
    @Autowired
    private ImportService importService;

    @Async
    public void import() {
        importService.import();
    }
}

ImportService.java

@Service
public class ImportService {
    @Autowired
    private AddressCrudRepository addressRepository;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void import() {
        List<Adres> adresses = new ArrayList<>();

        // Open file and create buffered reader using try-with-resources
        try (BufferedReader reader = ...) {
            while((line = reader.readLine()) != null) {
                // mapAddress converts a line of text to an Address object
                addresses.add(mapAddress(line));
            }

            addressRepository.save(adresses);
        } catch (IOException e) {
            // Handle exception
        }
    }
}

AdresCrudRepository.java

public interface AddressCrudRepository extends CrudRepository<Address, Long> {
}

Я ожидаю, что мои адреса будут сохранены в БД, но после запуска задания (без получения ошибок или предупреждений),БД остается пустой.

Я смотрю на это часами, все идеи приветствуются!

1 Ответ

0 голосов
/ 03 мая 2019

Может быть транзакция, уже запущенная, когда вызывается @Async, и, таким образом, асинхронный метод выбирает тот же транзакционный контекст.

Обратной стороной является то, что до завершения асинхронного метода транзакция могла быть зафиксирована родительским кодом.

Обычно рекомендуется вызывать асинхронные методы с новой / вложенной транзакцией:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void import() {

Благодаря этому она не будет зависеть от родительской транзакции.

UPDATE

Также вы сохраняете Список сущностей. Попробуйте использовать:

addressRepository.saveAll(adresses);
...