← Назад к вопросам

Как работает транзакция в Spring Data JPA?

2.0 Middle🔥 241 комментариев
#ORM и Hibernate#Spring Boot и Spring Data

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает транзакция в Spring Data JPA?

Транзакция — это набор операций с базой данных, которые либо все выполняются успешно (commit), либо все откатываются (rollback). Spring Data JPA управляет транзакциями автоматически через аннотацию @Transactional.

Основной механизм

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    @Transactional
    public void createUser(String email, String name) {
        User user = new User();
        user.setEmail(email);
        user.setName(name);
        userRepository.save(user);
    }
}

Жизненный цикл транзакции

1. Начало транзакции (BEGIN TRANSACTION)
2. Выполнение SQL операций
3a. Успех - COMMIT
3b. Ошибка - ROLLBACK
4. Закрытие соединения с БД

Уровни изоляции

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void operation1() { }

@Transactional(isolation = Isolation.READ_COMMITTED)
public void operation2() { }

@Transactional(isolation = Isolation.REPEATABLE_READ)
public void operation3() { }

@Transactional(isolation = Isolation.SERIALIZABLE)
public void operation4() { }

Тип пропагации

@Transactional(propagation = Propagation.REQUIRED)
public void save(User user) { }

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logAction(String action) { }

@Transactional(propagation = Propagation.SUPPORTS)
public User findById(Long id) { }

Управление откатом

@Transactional(
    rollbackFor = Exception.class,
    noRollbackFor = ValidationException.class
)
public void processPayment(Payment payment) throws Exception {
    paymentRepository.save(payment);
}

ReadOnly флаг

@Transactional(readOnly = true)
public List<User> getAllUsers() {
    return userRepository.findAll();
}

Timeout

@Transactional(timeout = 10)
public void heavyOperation() {
}

Вложенные транзакции

@Service
public class UserService {
    @Autowired
    private AuditService auditService;
    
    @Transactional
    public void registerUser(String email) {
        auditService.logAudit("User created");
    }
}

@Service
public class AuditService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logAudit(String message) { }
}

Пример transfer денег

@Service
public class BankService {
    @Autowired
    private AccountRepository accountRepository;
    
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountRepository.findById(fromId).orElseThrow();
        Account to = accountRepository.findById(toId).orElseThrow();
        
        if (from.getBalance().compareTo(amount) < 0) {
            throw new InsufficientFundsException();
        }
        
        from.setBalance(from.getBalance().subtract(amount));
        to.setBalance(to.getBalance().add(amount));
        
        accountRepository.save(from);
        accountRepository.save(to);
    }
}

Важные моменты

  1. Spring использует AOP для интерцепции методов с @Transactional
  2. Только на публичных методах работает, приватные методы не управляются
  3. Внутренний вызов через this не создаёт прокси
  4. Checked exceptions НЕ вызывают rollback по умолчанию
  5. RuntimeExceptions вызывают rollback автоматически

Оптимизация

  1. Минимизируй scope — только необходимые операции
  2. Используй readOnly для чтения — улучшает производительность
  3. Выбирай правильный isolation level — баланс между безопасностью и скоростью
  4. Избегай deadlock — консистентный порядок доступа
  5. Кэшируй данные — снизь нагрузку на БД

Транзакции в Spring Data JPA обеспечивают целостность данных и атомарность операций.