I'm wondering what is the recomended way to proceed in the following scenario:
ReportService
responsible for generating a report, uploading it, sending an email and saving it on database.So it would be something like:
@Service
public class ReportService {
public void generateReport() {
var entities = entityRepository.findEntities();
var file = getReportData(entities);
var url = uploadFile(file);
sendEmail(url);
// If something goes wrong while save on entity, roll back everything
for (var e : entities) {
entityRepository.save(e);
}
}
}
So the options I know I have are:
@Transactional
: I don't think this is a good idea because we would be mixing HTTP requests and workload with database transactionReportSavingService
, and having a method to only save those entities: This would work I think but it seems strange to me having an specific service dealing with the same business logic I already have a service for, just to save it...What I am wondering is if those are the solutions we have dealing with Spring Data or if there is an easy way to do something like:
// ...
sendEmail(url);
// If something goes wrong while save on entity, roll back everything
database.beginTransaction();
for (var e : entities) {
entityRepository.save(e);
}
database.commit();
I know we have that kind of control going down a bit, using EntityManager
directly, but then I cannot mix it with Spring Data's repositories methods... Can I?
What you are looking for is the TransactionTemplate
@Autowired
TransactionTemplate tx;
// ...
tx.execute(__ -> {
for (var e : entities) {
entityRepository.save(e);
}
}
I do agree with @crizzis comment that the design seems somewhat wrong, but I consider that somewhat besides the question.