Semyon Kirekov
Semyon Kirekov

Reputation: 1442

Spring Data - Archiving best practices

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

Answers (1)

asgarov1
asgarov1

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

Related Questions