Làm thế nào để sử dụng @Transactional với Spring Data?


82

Tôi mới bắt đầu làm việc trên một dự án Spring-data, Hibernate, MySQL, JPA. Tôi đã chuyển sang dữ liệu mùa xuân để không phải lo lắng về việc tạo truy vấn bằng tay.

Tôi nhận thấy rằng việc sử dụng @Transactionalkhông bắt buộc khi bạn đang sử dụng spring-data vì tôi cũng đã thử các truy vấn của mình mà không có chú thích.

Có lý do cụ thể nào khiến tôi nên / không nên sử dụng @Transactionalchú thích không?

Làm:

@Transactional
public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

Cũng hoạt động:

public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

Cảm ơn trước!

Câu trả lời:


140

Câu hỏi của bạn thực sự là về cái gì? Việc sử dụng @Repositorychú thích hoặc @Transactional.

@Repositoryhoàn toàn không cần thiết vì giao diện bạn khai báo sẽ được hỗ trợ bởi một proxy mà cơ sở hạ tầng Dữ liệu Mùa xuân tạo và kích hoạt dịch ngoại lệ. Vì vậy, việc sử dụng chú thích này trên giao diện kho lưu trữ Dữ liệu Mùa xuân hoàn toàn không có bất kỳ ảnh hưởng nào.

@Transactional- đối với mô-đun JPA, chúng tôi có chú thích này trên lớp triển khai hỗ trợ proxy ( SimpleJpaRepository). Điều này là vì hai lý do: thứ nhất, việc duy trì và xóa các đối tượng yêu cầu một giao dịch trong JPA. Vì vậy, chúng tôi cần đảm bảo rằng một giao dịch đang chạy, điều này chúng tôi thực hiện bằng cách có chú thích phương thức @Transactional.

Việc đọc các phương pháp như findAll()findOne(…)đang sử dụng @Transactional(readOnly = true)không hoàn toàn cần thiết nhưng kích hoạt một số tối ưu hóa trong cơ sở hạ tầng giao dịch (đặt thành FlushModeđể MANUALcho phép các nhà cung cấp liên tục có khả năng bỏ qua các kiểm tra bẩn khi đóng EntityManager). Ngoài ra, cờ được đặt trên Kết nối JDBC cũng là nguyên nhân tối ưu hóa hơn nữa ở cấp độ đó.

Tùy thuộc vào cơ sở dữ liệu bạn sử dụng, nó có thể bỏ qua các khóa bảng hoặc thậm chí từ chối các thao tác ghi mà bạn có thể vô tình kích hoạt. Vì vậy, chúng tôi khuyên bạn nên sử dụng @Transactional(readOnly = true)cho các phương thức truy vấn mà bạn có thể dễ dàng đạt được việc thêm chú thích đó vào giao diện kho lưu trữ của mình. Đảm bảo rằng bạn thêm đơn giản @Transactionalvào các phương thức thao tác mà bạn có thể đã khai báo hoặc trang trí lại trong giao diện đó.


8
Tóm lại: Tôi có nên sử dụng @Transactional trên các truy vấn thêm / sửa / xóa và @Transaction (readOnly = true) trên các truy vấn được chọn trên tất cả các phương thức DAO của mình không?
Byron Voorbach

20
Chính xác. Cách dễ nhất để làm như vậy là sử dụng @Transactional(readOnly = true)trên giao diện (vì nó thường chứa hầu hết các phương thức tìm kiếm) và ghi đè cài đặt này cho mỗi phương pháp truy vấn sửa đổi bằng một cách đơn giản @Transactional. Đó thực sự là cách nó được thực hiện SimpleJpaRepositoy.
Oliver Drotbohm

@Oliver, cảm ơn bạn đã giải thích toàn diện..Nhưng trong khi truy cập liên kết khác [transaction-pit-fall] < ibm.com/developerworks/java/library/j-ts1/index.html#listing8 >. Nó nói rằng " Điểm mấu chốt là khi bạn sử dụng một khuôn khổ dựa trên ORM, cờ chỉ đọc khá vô dụng và trong hầu hết các trường hợp bị bỏ qua. Nhưng nếu bạn vẫn khăng khăng sử dụng nó, hãy luôn đặt chế độ lan truyền thành HỖ TRỢ " . .Sau khi đọc phần này, tôi không chắc liệu mình có nên sử dụng (readOnly = true) một mình không .. có nên luôn sử dụng nó với chế độ lan truyền là SUPPORTS hay không.
Anupam Gupta

8
Gần với tất cả mọi thứ là sai trong phần này của bài viết. Bằng cách chỉ ra rằng bạn không viết, JDBC được điều khiển có thể (sẽ) cải thiện hiệu suất cho các tương tác DB. Nó cũng có thể phát hiện và từ chối các ghi vô tình được phát hành. Trên hết, Spring vô hiệu hóa JPA / Hibernate xả ở chế độ chỉ đọc, điều này có thể ảnh hưởng lớn đến hiệu suất trong trường hợp bạn đọc đồ thị đối tượng lớn vì khi đó nhà cung cấp không cần thực hiện kiểm tra bẩn trên nó. Mặc dù vậy, lá cờ có thể không có tác động lớn đến giao dịch, nhưng đó không phải là mọi thứ để xem xét.
Oliver Drotbohm

Tôi có thể đảm bảo cho những cải tiến về hiệu suất trong trường hợp đồ thị đối tượng lớn hoặc trường hợp sử dụng tải số lượng lớn đối tượng được quản lý.
Shailendra

3

Tôi nghĩ rằng câu hỏi rộng hơn một chút và không thể giảm bớt trên các chú thích trên lớp truy cập dữ liệu. Chúng tôi cần xem xét toàn bộ ngăn xếp của ứng dụng, các chiến lược giao dịch mà chúng tôi muốn áp dụng, v.v. Có một bộ bài viết rất toàn diện về chủ đề này của Mark Richards trên trang web developerworks của IBM. Bạn có thể tìm thấy cái đầu tiên ở đây: https://developer.ibm.com/articles/j-ts1/

Trân trọng


2

Bạn nên sử dụng @Repositorychú thích

Điều này là do @Repositoryđược sử dụng để dịch ngoại lệ SQL không được kiểm tra của bạn thành Spring Excpetion và ngoại lệ duy nhất bạn nên đối phó làDataAccessException


10
Điều này nói chung đúng khi sử dụng Spring, nhưng vì các kho lưu trữ Dữ liệu của Spring đã được hỗ trợ bởi một proxy Spring - việc sử dụng @Repository không tạo ra bất kỳ sự khác biệt nào.
Aleksander Blomskøld

0

Chúng tôi cũng sử dụng chú thích @Transactional để khóa bản ghi để luồng / yêu cầu khác không thay đổi nội dung đọc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.