ENIGMA AI
ENIGMA AI
Java Сложный

Как работает аннотация @Transactional?

@Transactional в Spring

Как работает:

Spring создаёт proxy вокруг класса/метода:

@Service
public class UserService {

    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
        auditService.log("User created");
    }
}

Proxy делает:

  1. Открывает транзакцию
  2. Вызывает метод
  3. Commit при успехе / Rollback при исключении

Параметры:

@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED,
    timeout = 30,
    readOnly = false,
    rollbackFor = Exception.class,
    noRollbackFor = BusinessException.class
)

Propagation (распространение):

Тип Описание
REQUIRED Использовать текущую или создать новую
REQUIRES_NEW Всегда новая (приостанавливает текущую)
NESTED Вложенная (savepoint)
SUPPORTS Использовать если есть, иначе без
NOT_SUPPORTED Выполнять без транзакции
MANDATORY Требует существующую
NEVER Ошибка если есть транзакция

Isolation (изоляция):

@Transactional(isolation = Isolation.SERIALIZABLE)
public void criticalOperation() { }
  • READ_UNCOMMITTED — dirty reads
  • READ_COMMITTED — нет dirty reads
  • REPEATABLE_READ — нет non-repeatable reads
  • SERIALIZABLE — полная изоляция

Типичные ошибки:

1. Self-invocation (не работает):

@Service
public class UserService {

    public void methodA() {
        methodB();  // @Transactional НЕ сработает!
    }

    @Transactional
    public void methodB() { }
}

// Решение: вынести в другой сервис или использовать self-injection

2. Checked exceptions (не откатывают):

@Transactional  // По умолчанию откатывает только RuntimeException
public void process() throws IOException {
    // IOException не откатит транзакцию!
}

// Решение:
@Transactional(rollbackFor = Exception.class)

3. Private методы:

@Transactional  // НЕ работает на private!
private void privateMethod() { }

Best Practices:

  1. Используйте на уровне сервисов, не репозиториев
  2. Делайте транзакции короткими
  3. Указывайте readOnly=true для чтения
  4. Логируйте откаты
@Transactional(readOnly = true)
public List<User> getUsers() {
    return userRepository.findAll();
}

Похожие вопросы

Готовитесь к собеседованию?

ENIGMA AI — невидимый ИИ-помощник для технических интервью

Попробовать бесплатно
Все вопросы