Лабораторная работа 5: Транзакции и кэширование в Spring Boot приложении с PostgreSQL
1. Настройка транзакций
- Активация транзакций
@EnableTransactionManagement @SpringBootApplication public class Application { ... } - Простая транзакция
@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)); } - Уровни изоляции
@Transactional(isolation = Isolation.SERIALIZABLE) public void criticalOperation() { ... } - Параметры propagation
@Transactional(propagation = Propagation.REQUIRES_NEW) public void auditLog(String action) { ... } - Только для чтения
@Transactional(readOnly = true) public List<Account> getAllAccounts() { ... } - Ручное управление
@Autowired private TransactionTemplate transactionTemplate; public void manualTransaction() { transactionTemplate.execute(status { // Бизнес-логика return null; }); } - Таймаут транзакции
@Transactional(timeout = 30) public void longRunningProcess() { ... } - Обработка исключений
@Transactional(rollbackFor = BusinessException.class) public void processOrder() throws BusinessException { ... } - Неоткатываемые исключения
@Transactional(noRollbackFor = IllegalArgumentException.class) - Транзакции в тестах
@SpringBootTest @Transactional class AccountServiceTest { ... } - Распределенные транзакции (JTA)
spring.jta.enabled=true - Синхронизация с БД
entityManager.flush(); - Точки сохранения (Savepoints)
Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint(); // ... TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint); - Логирование транзакций
logging.level.org.springframework.transaction.interceptor=TRACE - Оптимизация bulk-операций
@Transactional public void bulkInsert(List<Entity> items) { items.forEach(entityManager::persist); entityManager.flush(); entityManager.clear(); }
2. Настройка кэширования
- Активация кэширования
@EnableCaching @SpringBootApplication public class Application { ... } - Простое кэширование
@Cacheable("products") public Product getProductById(Long id) { return productRepository.findById(id).orElseThrow(...); } - Ключи кэша
@Cacheable(value = "products", key = "#root.methodName + #id") - Условное кэширование
@Cacheable(value = "products", condition = "#id > 10") - Обновление кэша
@CachePut(value = "products", key = "#result.id") public Product updateProduct(Product product) { ... } - Инвалидация кэша
@CacheEvict(value = "products", key = "#id") public void deleteProduct(Long id) { ... } - Очистка всего кэша
@CacheEvict(value = "products", allEntries = true) public void reloadAllProducts() { ... } - Многоуровневое кэширование
@Caching(evict = { @CacheEvict("primary"), @CacheEvict("secondary") }) - Настройка TTL
spring.cache.caffeine.spec=maximumSize=500,expireAfterWrite=10m - Ручное управление
@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(...);
}
}
Вывод
В ходе работы были реализованы:
- Полноценное управление транзакциями с различными уровнями изоляции
- Гибкая система кэширования с ручным и автоматическим управлением
- Оптимизация производительности за счет комбинации подходов
- Обработка исключительных ситуаций в распределенных операциях