Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Propagation в Spring
Propagation (распространение) в Spring определяет, как транзакция ведет себя при вызове другого метода с @Transactional внутри уже выполняющейся транзакции. Это управление жизненным циклом транзакций.
Основные типы Propagation
1. REQUIRED (по умолчанию)
Это наиболее часто используемое значение. Использует текущую транзакцию, если она есть. Если нет — создает новую.
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@Transactional(propagation = Propagation.REQUIRED)
public void processOrder(Order order) {
// Если есть активная транзакция, используем её
// Если нет — создаем новую
saveOrder(order);
paymentService.processPayment(order);
// Если processPayment выбросит исключение,
// вся транзакция откатится
}
@Transactional(propagation = Propagation.REQUIRED)
public void processPayment(Order order) {
// Использует ту же транзакцию что и processOrder
paymentRepository.save(payment);
}
}
2. REQUIRES_NEW
Засчитает новую транзакцию, приостанавливая текущую (если она есть).
@Service
public class OrderService {
@Autowired
private LoggingService loggingService;
@Transactional(propagation = Propagation.REQUIRED)
public void createOrder(Order order) {
orderRepository.save(order);
loggingService.logOrderCreation(order); // новая транзакция
}
}
@Service
public class LoggingService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOrderCreation(Order order) {
// Эта транзакция будет независимой
// Даже если основной заказ откатится, лог сохранится
logRepository.save(new Log("Order created"));
}
}
Практический пример: логирование должно быть отдельной транзакцией, чтобы ошибка в основной операции не удаляла логи.
3. SUPPORTED
Использует текущую транзакцию, если она есть. Если нет — выполняется без транзакции.
@Service
public class ReportService {
@Transactional(propagation = Propagation.SUPPORTED, readOnly = true)
public Report generateReport() {
// Если есть транзакция, используем её
// Если нет — просто читаем данные
return reportRepository.findAll();
}
}
4. NOT_SUPPORTED
Выполняется БЕЗ транзакции. Если есть текущая транзакция, она приостанавливается.
@Service
public class ExternalService {
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void callExternalAPI() {
// Выполняется без транзакции
// Полезно для вызовов, которые не должны быть в транзакции
externalApi.call();
}
}
5. MANDATORY
Требует наличие активной транзакции. Если её нет — выбросит исключение.
@Service
public class PaymentService {
@Transactional(propagation = Propagation.MANDATORY)
public void processPayment(Payment payment) {
// Этот метод ДОЛЖЕН быть вызван в контексте транзакции
// Иначе будет thrown IllegalTransactionStateException
paymentRepository.save(payment);
}
}
// Вызов без транзакции приведет к ошибке
paymentService.processPayment(payment); // ERROR!
// Правильный вызов внутри другого @Transactional метода
@Transactional
public void orderWithPayment(Order order) {
processPayment(order.getPayment()); // OK
}
6. NEVER
Никогда не должна быть активной транзакция. Если она есть — выбросит исключение.
@Service
public class AuditService {
@Transactional(propagation = Propagation.NEVER)
public void auditAction(String action) {
// Этот метод НЕ должен быть в транзакции
auditRepository.save(action);
}
}
7. NESTED
Создает вложенную транзакцию (savepoint). Если вложенная откатится, основная может продолжить.
@Service
public class OrderService {
@Transactional
public void complexOrder(Order order) {
saveOrder(order);
try {
processDiscount(order); // вложенная транзакция
} catch (DiscountException e) {
// Откат только скидки, заказ остается
log.warn("Discount failed, order saved without discount");
}
}
@Transactional(propagation = Propagation.NESTED)
public void processDiscount(Order order) {
// Вложенная транзакция с savepoint
discountRepository.apply(order);
}
}
Сравнительная таблица
| Propagation | Текущая ТХ | Создает новую | Если ошибка |
|---|---|---|---|
| REQUIRED | Использует | Если нет | Откат всей ТХ |
| REQUIRES_NEW | Приостанавливает | Да | Откат только новой ТХ |
| SUPPORTED | Использует | Нет | Без ТХ |
| NOT_SUPPORTED | Приостанавливает | Нет | Без ТХ |
| MANDATORY | Требует | Нет | Ошибка если нет ТХ |
| NEVER | Ошибка | Нет | Ошибка если есть ТХ |
| NESTED | Вложенная | Savepoint | Откат только вложенной |
Практические примеры использования
// 1. Логирование независимо от основной операции
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String message) {
logRepository.save(new Log(message));
}
// 2. Операции, которые могут быть без транзакции
@Transactional(propagation = Propagation.SUPPORTED, readOnly = true)
public List<Report> getReports() {
return reportRepository.findAll();
}
// 3. Обязательное наличие транзакции
@Transactional(propagation = Propagation.MANDATORY)
public void criticalOperation() {
// Должна быть транзакция
}