@Transactional trong Spring: những hiểu lầm phổ biến
22/07/2026
Annotation @Transactional trông đơn giản nhưng ẩn chứa nhiều bẫy do cơ chế proxy của Spring. Hiểu sai dẫn tới transaction không hoạt động mà không hề báo lỗi.
Bẫy 1: gọi method nội bộ không có tác dụng
Spring bọc bean bằng proxy. Khi một method trong cùng class gọi method @Transactional khác qua this, lời gọi KHÔNG đi qua proxy nên transaction không được mở. Tách sang bean khác hoặc tự inject chính mình.
@Service
class OrderService {
public void process() {
save(); // gọi qua this -> KHÔNG có transaction!
}
@Transactional
public void save() { ... }
}
Bẫy 2: rollback mặc định chỉ với unchecked exception
Theo mặc định, Spring rollback khi gặp RuntimeException/Error, nhưng KHÔNG rollback với checked exception. Muốn rollback cả checked exception, khai báo @Transactional(rollbackFor = Exception.class).
Bẫy 3: readOnly không phải chỉ để làm cảnh
@Transactional(readOnly = true) cho truy vấn đọc giúp Hibernate bỏ dirty checking và gợi ý driver tối ưu. Đừng để readOnly cho method có ghi — sẽ lỗi hoặc mất dữ liệu.
Bẫy 4: method phải public
Proxy dựa trên JDK/CGLIB chỉ chặn được method public. @Transactional trên method private/protected bị bỏ qua âm thầm.
👉 Dùng thử công cụ liên quan trên dev-hub: JSON Formatter — chạy hoàn toàn trong trình duyệt, không gửi dữ liệu lên server.