@EnableTransactionManagement và @Transacitonal
Khi bạn cần sự hỗ trợ quản lý Transaction từ Spring Framework
Hãy nhớ đến @EnableTransactionManagement
Thật ra tôi áp dụng SpringBoot v2.1.2.RELEASE cũng không cần áp dụng Annotation này(vì quên). Nhưng thấy vẫn chạy ổn với @Transactional :-)
Với annotation này, bạn đang nói với Spring rằng bạn cần Spring quản lý Transaction cho bạn thay vì bạn sẽ làm việc đó thủ công
Done
Nhưng để Spring hiểu rằng một Transaction nào thì Spring sẽ quản lý
thì bạn cần phải đánh dấu các transaction cho SpringBoot hiểu với
@Transacitonal
javax.transaction.Transactional;
or
org.springframework.transaction.annotation.Transactional
Cả 2 annotation này để chạy ổn với rollback hoặc noRollback
Nếu bạn đặt level này ở mức class khai báo (cạnh @Service) thì nó sẽ có sức ảnh hươngr đến toàn bộ method khai báo bên trong class này
Nếu bạn muốn Overwrite ghi đè cho một phương thức nào đó thì bạn đặc thêm @Transactional ở level method.
Done
Bây giờ thì bạn muốn thử sức mạnh của nó
Chúng ta sẽ test bằng cách rollback Exception
1. Bình thường nếu bạn k dùng @transactional thì khi trường hợp này vẫn chạy ok và dữ liệu vẫn đẩy vào CSDL
@Override public Person save(Person person) { personRepo.save(person); throw new RuntimeException("haha"); }
WTF, tại sao nó vẫn lưu được thì là vì bạn chưa @Transactional cho nó
--> Để fix điều này, nghĩa là bạn muốn rollback thì đơn giản là Add cái @Transactional vào là OK
2. Tình huống tiếp theo là RuntimeException và not RuntimeException
Nếu bạn chưa biết phần biệt 2 cái này khác nhau thế nào thì cần đọc lại kiến thức Core
@Override @Transactional public Person save(Person person) { personRepo.save(person); throw new RuntimeException("haha"); }
Như bên trên tôi ném RuntimeException --> Rollback Ok , dữ liệu k bị đẩy vào DB như chúng ta mong muốn (Spring nó tự động rollBack khi excetion là Runtime)
Nhưng nếu tôi muốn ném một exception không phải loại RuntimeException , mà là một loại Checked Exception ví dự như <? extends Exception> đó là 1 class nào đó kế thừa Class Exception
@Override @Transactional public Person save(Person person) throws Exception { personRepo.save(person); throw new Exception("haha"); //k phải runtimeexception }
Trường hợp này thì Bạn chạy kết quả sẽ vẫn lưu vào DB, vì Exception không phải là loại RuntimeException (Spring nó chỉ tự động rollBack khi exception là Runtime)
Vậy làm thế nào để nó Rollback
đó là dùng thêm rollbackFor
@Override @Transactional(rollbackFor = Exception.class) public Person save(Person person) throws Exception { personRepo.save(person); throw new Exception("haha"); Đây k phải là RuntimeException }
Nếu config như này thì nó sẽ rollback OK cho bạn, Dữ liệu sẽ k bị đẩy vào DB, đã test
3. Tình huống tiếp theo, Nếu chúng ta muốn nó không RollBack cho một số RuntimeException nào đó
thì dùng noRollbackFor = RuntimeException.class
@Override @Transactional(noRollbackFor = RuntimeException.class) public Person save(Person person) throws Exception { personRepo.save(person); throw new RuntimeException("haha"); //<--- là RuntimeException }
Nếu bạn đã chỉ rõ tên RuntimeException bên trên rồi, thì nó sẽ không rollBack nếu ngoại lệ đó được ném ra, đồng nghĩa với ví dụ trên sẽ vẫn lưu dữ liệu OK vào DB
Vậy là các bạn có thể tự tin chơi với cái @Transactional nhé
Chú ý
javax.transaction.Transactional (rollbackOn= Exception.class, dontRollbackOn= RuntimeException.class)
hoạt động tương tự như
org.springframework.transaction.annotation.Transactional (rollbackFor = Exception.class, noRollbackFor=RuntimeException.class)
Comments
Post a Comment