← Tất cả bài viết

@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.