Propagation xác định hành vi khi method @Transactional được gọi từ trong một transaction đang có.
| Propagation | Hành vi |
|---|---|
| REQUIRED (default) | Join transaction hiện có, nếu không có → tạo mới |
| REQUIRES_NEW | Luôn tạo transaction mới, suspend cái cũ |
| NESTED | Nested trong transaction hiện có (savepoint) |
| SUPPORTS | Join nếu có, không có thì chạy không transaction |
| NOT_SUPPORTED | Suspend transaction hiện có, chạy không transaction |
| MANDATORY | Phải có transaction, không có → exception |
| NEVER | Không được có transaction, có → exception |
Ví dụ thực tế:
java
@Service
class OrderService {
@Transactional
public void processOrder(Order order) {
orderRepo.save(order);
auditService.log(order); // REQUIRES_NEW → log dù order fail
}
}
@Service
class AuditService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(Order order) {
auditRepo.save(new AuditLog(order)); // transaction riêng, luôn commit
}
}REQUIRES_NEW dùng khi: audit log, notification — phải persist dù outer transaction rollback.
NESTED dùng khi: thử save, nếu fail thì rollback chỉ phần đó (savepoint), không rollback outer.
Propagation defines the behaviour when a @Transactional method is called from within an existing transaction.
| Propagation | Behaviour |
|---|---|
| REQUIRED (default) | Joins existing transaction, creates one if none |
| REQUIRES_NEW | Always creates a new transaction, suspends the current one |
| NESTED | Nested inside current transaction (savepoint) |
| SUPPORTS | Joins if present, runs non-transactionally if not |
| NOT_SUPPORTED | Suspends current transaction, runs non-transactionally |
| MANDATORY | Must have a transaction; throws if none |
| NEVER | Must not have a transaction; throws if one exists |
Real-world example:
java
@Service
class OrderService {
@Transactional
public void processOrder(Order order) {
orderRepo.save(order);
auditService.log(order); // REQUIRES_NEW → logged even if order fails
}
}
@Service
class AuditService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(Order order) {
auditRepo.save(new AuditLog(order)); // own transaction, always committed
}
}REQUIRES_NEW is used for: audit logs, notifications — must persist even if the outer transaction rolls back.
NESTED is used for: try-save-partial — rolls back only that section (savepoint), not the outer transaction.