Reputation: 1442
Suppose that I have entities Rule
and RuleArchive
. Every time one make changes to Rule
is is required to persist the previous state to RuleArchiveTable
. I came around with this solution:
class CustomRuleRepositoryImpl implements CustomRuleRepository {
private final RuleRepository ruleRepository;
private final RuleArchiveRepository ruleArchiveRepository;
@Override
public Rule saveAndFlushWithArchiveRecordCreated(Rule rule) {
ofNullable(rule.getId())
.flatMap(ruleRepository::findById)
.ifPresent(this::createNewArchiveRecord);
return ruleRepository.saveAndFlush(rule);
}
private void createNewArchiveRecord(Rule oldRule) {
ruleArchiveRepository.saveAndFlush(
RuleArchive.builder()
// building the entity from 'oldRule' fields
.build()
);
}
}
The thing I'm worried about is concurrency. Although the system is not of highload type, there could be some caveats. For example, when I read the rule with ruleRepository
it is possible that somebody has already changed it. So, the values from the archived version and the saved rule won't be consistent.
Any ideas about this approach? Are there any better alternatives? I thought that I could just use repeatable read
isolation (we use PostgreSQL), so it would guaranteed that the fetched records are the same during the whole transaction.
Upvotes: 0
Views: 1071
Reputation: 4161
This would prevent dirty reads:
@Transactional(isolation = Isolation.READ_COMMITTED)
More here https://www.baeldung.com/spring-transactional-propagation-isolation
Important to note that while isolation levels prevent dirty reads they won’t prevent race conditions - for that you would still need to use synchronized (which funnily could solve both of your problems provided only this method is doing the saving)
Upvotes: 1