← Назад к вопросам
Что такое propagation level в Spring Data?
2.0 Middle🔥 201 комментариев
#Spring Boot и Spring Data#Spring Framework
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Propagation Level в Spring Data (Транзакции)
Propagation level (уровень распространения) — это настройка, определяющая как транзакция ведёт себя при вложенных вызовах методов, помеченных @Transactional. Это критично для управления границами транзакций в многоуровневых приложениях.
Основные режимы распространения
REQUIRED (по умолчанию)
- Использует текущую транзакцию если она существует
- Создаёт новую если транзакции нет
- Наиболее часто используемый режим
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentService paymentService;
@Transactional(propagation = Propagation.REQUIRED)
public Order createOrder(Order order) {
Order saved = orderRepository.save(order);
// paymentService тоже работает в этой же транзакции
paymentService.processPayment(saved);
return saved;
}
}
@Service
public class PaymentService {
@Autowired
private PaymentRepository paymentRepository;
@Transactional(propagation = Propagation.REQUIRED)
public void processPayment(Order order) {
// Работает в ТОЙ ЖЕ транзакции, что и createOrder
Payment payment = new Payment(order);
paymentRepository.save(payment);
}
}
REQUIRES_NEW
- ВСЕГДА создаёт новую транзакцию
- Suspend текущей транзакции (если была)
- Используется когда нужна независимость
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private AuditService auditService;
@Transactional(propagation = Propagation.REQUIRED)
public Order createOrder(Order order) {
Order saved = orderRepository.save(order);
// ТРЕБУЕТ_NEW — даже если ошибка здесь, audit сохранится
auditService.logOrderCreation(saved);
return saved;
}
}
@Service
public class AuditService {
@Autowired
private AuditRepository auditRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOrderCreation(Order order) {
// Независимая транзакция
// Коммитится ОТДЕЛЬНО от createOrder
Audit audit = new Audit("ORDER_CREATED", order.getId());
auditRepository.save(audit);
}
}
SUPPORTED
- Использует текущую транзакцию если она есть
- Работает БЕЗ транзакции если её нет
- Гибкий режим для read-only операций
@Transactional(propagation = Propagation.SUPPORTED, readOnly = true)
public List<Order> getOrders() {
// Если вызвано из @Transactional метода — работает в этой транзакции
// Если вызвано как обычный метод — работает БЕЗ транзакции
return orderRepository.findAll();
}
NOT_SUPPORTED
- НЕ использует транзакцию
- Suspend текущей транзакции
- Используется редко, для операций которые не должны быть transactional
@Transactional
public void mainTransaction() {
orderRepository.save(order);
// Эта операция вне транзакции
notTransactionalOperation();
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void notTransactionalOperation() {
// Текущая транзакция будет suspended
}
MANDATORY
- ТРЕБУЕТ существования транзакции
- Выбросит исключение если нет
- Используется для критических операций
@Transactional(propagation = Propagation.MANDATORY)
public void onlyInTransaction() {
// Если вызвано БЕЗ транзакции — IllegalTransactionStateException
// Гарантирует что метод ВСЕГДА в транзакции
database.update(data);
}
NEVER
- ЗАПРЕЩАЕТ транзакцию
- Выбросит исключение если транзакция активна
- Противоположность MANDATORY
NESTED
- Использует savepoints внутри существующей транзакции
- Позволяет откатить часть логики БЕЗ отката всего
@Transactional
public void mainOperation() {
save(data1);
try {
nestedOperation(); // Может откатиться независимо
} catch (Exception e) {
// data1 остался, data2 откатился
}
}
@Transactional(propagation = Propagation.NESTED)
public void nestedOperation() {
save(data2); // Savepoint
}
Практические примеры
// User Service — основная логика
@Service
public class UserService {
@Transactional(propagation = Propagation.REQUIRED)
public User registerUser(UserRegisterRequest req) {
User user = new User(req);
userRepository.save(user);
// Отправка email в отдельной транзакции (может упасть)
emailService.sendWelcomeEmail(user);
// Логирование в отдельной транзакции (всегда должна быть)
auditService.logRegistration(user);
return user;
}
}
// Email Service — может отдельно откатиться
@Service
public class EmailService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void sendWelcomeEmail(User user) {
// Даже если упадёт, user уже в БД
}
}
// Audit Service — всегда записывает
@Service
public class AuditService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logRegistration(User user) {
// Независимая запись
}
}
Выбор правильного уровня
- REQUIRED — стандарт, используй по умолчанию
- REQUIRES_NEW — когда нужна независимость (audit, notifications)
- SUPPORTED — для read-only операций
- MANDATORY/NEVER — для enforcing constraints
- NESTED — редко, когда нужны savepoints
Неправильный выбор уровня может привести к deadlocks, несогласованности данных или потере изменений.