I currently have a use case, where I where if my user manually inserts a data file to be read into the database I need to check if the data exists in the DB. If it does, I want to delete it and then process and save the new file. The problem with this is my methods are marked @Transactional so even though the delete methods are ran, they aren't committed before the save method is called which violates a unique constraint casuing the rollback.
I have tried every level of propagation and also tried splitting them up into two separate transactions where my controller calls them one by one and they don't call each other.
ERROR: org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
CODE:
@Transactional
public void saveAllPositionData(InputStream is) throws IOException {
log.info("Parsing position data...");
ParsingResult parsingResult = positionParser.parse(is);
if (!parsingResult.getPositions().isEmpty()) {
LocalDate businessDate = parsingResult.getPositions().get(0).getBusinessDate();
overwriteData(businessDate);
}
try {
positionRepo.saveAll(bpsParsingResult.getPositions()); // UNIQUE CONSTRAINT FAILS HERE CAUSING ROLLBACK
priceRepo.saveAll(parsingResult.getPrices());
for (PositionTable position : parsingResult.getPositions()) {
if (position.getNumberOfMemos() > 0) memoRepo.saveAll(position.getCorrespondingMemos());
}
} catch (Exception e) {
log.warn("Invalid data returned from BPS parsing job: {}", e.getMessage());
}
}
@Transactional(propagation = Propagation.NESTED) // Tried Propagation.* and no Annotation
public void overwriteData(LocalDate businessDate) {
if (memoRepo.countByBusinessDate(businessDate) > 0) {
log.warn(
"Memo record(s) found by {} business date. Existing data will be overridden.",
businessDate);
memoRepo.deleteByBusinessDate(businessDate);
}
if (positionRepo.countByBusinessDate(businessDate) > 0) {
log.warn(
"Position record(s) found by {} business date. Existing data will be overridden.",
businessDate);
positionRepo.deleteByBusinessDate(businessDate);
}
if (priceRepo.countByBusinessDate(businessDate) > 0) {
log.warn(
"Price record(s) found by {} business date. Existing data will be overridden.",
businessDate);
priceRepo.deleteByBusinessDate(businessDate);
}
}