Reputation: 31
I need to run an asynchronous job that imports data (read from a file) to a MySQL DB. I am using Spring Data's CrudRepository
. The problem is that despite calling the save method, no data is persisted to the DB.
Honestly, I do not know how to start solving this issue. I am not seeing any errors or warnings in my logs, and searching on Google I only found the following suggestion:
Spring JPA: Data not saved to Database when processing from an Async method
However, I have already applied it, and my code is still not working. Running the code synchronously (by removing the @Async
annotation), everything works as expected.
A snippet of my code:
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> {
}
I expect my addresses to be saved to the DB, but after running the job (and not getting any errors or warnings), the DB remains empty.
I have been staring at this for hours, all ideas are welcome!
Upvotes: 3
Views: 2051
Reputation: 26552
There may be a transaction already running when the @Async
is invoked and thus the asynchronous method picks the same transactional context.
The flip side is that before the async method finishes the transaction may have been committed by the parent code.
In general, it is advisable to invoke async methods with a new / nested transaction:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void import() {
Thanks to that it will not be dependent on the parent transaction.
UPDATE
Also you are saving a List of entities. Try using:
addressRepository.saveAll(adresses);
Upvotes: 0