Лабораторная работа 5: Транзакции и кэширование в Spring Boot приложении с PostgreSQL

1. Настройка транзакций

  1. Активация транзакций
    
    @EnableTransactionManagement
    @SpringBootApplication
    public class Application { ... }
        
  2. Простая транзакция
    
    @Transactional
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountRepository.findById(fromId).orElseThrow(...);
        Account to = accountRepository.findById(toId).orElseThrow(...);
    
        from.withdraw(amount);
        to.deposit(amount);
    
        accountRepository.saveAll(List.of(from, to));
    }
        
  3. Уровни изоляции
    
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void criticalOperation() { ... }
        
  4. Параметры propagation
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void auditLog(String action) { ... }
        
  5. Только для чтения
    
    @Transactional(readOnly = true)
    public List<Account> getAllAccounts() { ... }
        
  6. Ручное управление
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    public void manualTransaction() {
        transactionTemplate.execute(status  {
            // Бизнес-логика
            return null;
        });
    }
        
  7. Таймаут транзакции
    
    @Transactional(timeout = 30)
    public void longRunningProcess() { ... }
        
  8. Обработка исключений
    
    @Transactional(rollbackFor = BusinessException.class)
    public void processOrder() throws BusinessException { ... }
        
  9. Неоткатываемые исключения
    
    @Transactional(noRollbackFor = IllegalArgumentException.class)
        
  10. Транзакции в тестах
    
    @SpringBootTest
    @Transactional
    class AccountServiceTest { ... }
        
  11. Распределенные транзакции (JTA)
    
    spring.jta.enabled=true
        
  12. Синхронизация с БД
    
    entityManager.flush();
        
  13. Точки сохранения (Savepoints)
    
    Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
    // ...
    TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
        
  14. Логирование транзакций
    
    logging.level.org.springframework.transaction.interceptor=TRACE
        
  15. Оптимизация bulk-операций
    
    @Transactional
    public void bulkInsert(List<Entity> items) {
        items.forEach(entityManager::persist);
        entityManager.flush();
        entityManager.clear();
    }
        

2. Настройка кэширования

  1. Активация кэширования
    
    @EnableCaching
    @SpringBootApplication
    public class Application { ... }
        
  2. Простое кэширование
    
    @Cacheable("products")
    public Product getProductById(Long id) {
        return productRepository.findById(id).orElseThrow(...);
    }
        
  3. Ключи кэша
    
    @Cacheable(value = "products", key = "#root.methodName + #id")
        
  4. Условное кэширование
    
    @Cacheable(value = "products", condition = "#id > 10")
        
  5. Обновление кэша
    
    @CachePut(value = "products", key = "#result.id")
    public Product updateProduct(Product product) { ... }
        
  6. Инвалидация кэша
    
    @CacheEvict(value = "products", key = "#id")
    public void deleteProduct(Long id) { ... }
        
  7. Очистка всего кэша
    
    @CacheEvict(value = "products", allEntries = true)
    public void reloadAllProducts() { ... }
        
  8. Многоуровневое кэширование
    
    @Caching(evict = {
        @CacheEvict("primary"),
        @CacheEvict("secondary")
    })
        
  9. Настройка TTL
    
    spring.cache.caffeine.spec=maximumSize=500,expireAfterWrite=10m
        
  10. Ручное управление
    
    @Autowired
    private CacheManager cacheManager;
    
    public void clearCache(String cacheName) {
        cacheManager.getCache(cacheName).clear();
    }
        

Пример интеграции


@Service
@RequiredArgsConstructor
public class AccountService {
    private final AccountRepository accountRepository;

    @Transactional(isolation = Isolation.READ_COMMITTED)
    @CacheEvict(value = "accounts", key = "#fromId + #toId")
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        // Логика перевода
    }

    @Cacheable(value = "accounts", sync = true)
    @Transactional(readOnly = true)
    public Account getAccount(Long id) {
        return accountRepository.findById(id).orElseThrow(...);
    }
}

Вывод

В ходе работы были реализованы:

  • Полноценное управление транзакциями с различными уровнями изоляции
  • Гибкая система кэширования с ручным и автоматическим управлением
  • Оптимизация производительности за счет комбинации подходов
  • Обработка исключительных ситуаций в распределенных операциях