Jak korzystać z @Transactional w Spring Data?

82

Właśnie zacząłem pracować nad projektem Spring-data, Hibernate, MySQL, JPA. Przerzuciłem się na spring-data, żeby nie musieć się martwić o ręczne tworzenie zapytań.

Zauważyłem, że użycie @Transactionalskryptu nie jest wymagane, gdy używasz danych wiosennych, ponieważ wypróbowałem również moje zapytania bez adnotacji.

Czy istnieje konkretny powód, dla którego powinienem / nie powinienem używać @Transactionaladnotacji?

Pracuje:

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

Działa również:

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

Z góry dziękuję!

Byron Voorbach
źródło

Odpowiedzi:

141

O co właściwie chodzi z twoim pytaniem? Użycie @Repositoryadnotacji lub @Transactional.

@Repositorynie jest w ogóle potrzebny, ponieważ deklarowany interfejs będzie obsługiwany przez proxy, które infrastruktura Spring Data tworzy i aktywuje tłumaczenie wyjątków. Zatem użycie tej adnotacji w interfejsie repozytorium Spring Data nie ma żadnego efektu.

@Transactional- dla modułu JPA mamy tę adnotację o klasie implementacji wspierającej proxy ( SimpleJpaRepository). Dzieje się tak z dwóch powodów: po pierwsze, utrwalanie i usuwanie obiektów wymaga transakcji w JPA. Dlatego musimy upewnić się, że transakcja jest uruchomiona, co robimy, mając przypisaną metodę@Transactional .

Czytanie metod jak findAll()i findOne(…)używania @Transactional(readOnly = true), które nie jest to bezwzględnie konieczne, ale wyzwala kilka optymalizacji w infrastrukturze transakcyjnej (ustawienie FlushModeaby MANUALpozwolić utrzymywanie dostawcy potencjalnie pominąć brudne kontrole podczas zamykania EntityManager). Poza tym flaga jest ustawiana również w połączeniu JDBC, co powoduje dalsze optymalizacje na tym poziomie.

W zależności od używanej bazy danych może pomijać blokady tabel lub nawet odrzucać operacje zapisu, które mogą zostać przypadkowo uruchomione. Dlatego zalecamy używanie również @Transactional(readOnly = true)dla metod zapytań, które można łatwo osiągnąć, dodając tę ​​adnotację do interfejsu repozytorium. Upewnij się, że dodałeś zwykły @Transactionaldo metod manipulacyjnych, które mogłeś zadeklarować lub ponownie ozdobić w tym interfejsie.

Oliver Drotbohm
źródło
9
Krótko mówiąc: powinienem używać @Transactional do dodawania / edycji / usuwania zapytań i @Transaction (readOnly = true) w przypadku wybranych zapytań we wszystkich moich metodach DAO?
Byron Voorbach
21
Dokładnie. Najłatwiejszym sposobem jest użycie @Transactional(readOnly = true)w interfejsie (ponieważ zwykle zawiera on głównie metody wyszukiwania) i zastąpienie tego ustawienia dla każdej modyfikującej metody zapytania zwykłym @Transactional. Właściwie tak to się robi SimpleJpaRepositoy.
Oliver Drotbohm
@Oliver dziękuje za obszerne wyjaśnienie, ale przechodząc przez inny link [transaction-pit-falls] < ibm.com/developerworks/java/library/j-ts1/index.html#listing8 >. Mówi: Najważniejsze jest to, że kiedy używasz frameworka opartego na ORM, flaga tylko do odczytu jest całkiem bezużyteczna iw większości przypadków jest ignorowana. Ale jeśli nadal nalegasz na jej używanie, zawsze ustaw tryb propagacji na WSPARCIE . Po przeczytaniu tego nie jestem pewien, czy powinienem używać samego (readOnly = true) .. czy zawsze powinien być używany z trybem propagacji jako WSPARCIE.
Anupam Gupta
9
Prawie wszystko jest nie tak w tej części artykułu. Wskazując, że nie piszesz, oparty na JDBC może (poprawi) wydajność interakcji z bazą danych. Może również wykrywać i odrzucać przypadkowo wydane zapisy. Ponadto Spring wyłącza opróżnianie JPA / Hibernacja w trybie tylko do odczytu, co może mieć ogromny wpływ na wydajność w przypadku odczytywania dużych wykresów obiektów, ponieważ dostawca nie musi wtedy wykonywać na nich brudnych sprawdzeń. Flaga może nie mieć dużego wpływu na samą transakcję, ale to zdecydowanie nie wszystko do rozważenia.
Oliver Drotbohm
Mogę ręczyć za poprawę wydajności w przypadku dużych wykresów obiektów lub przypadków użycia ładujących dużą liczbę zarządzanych obiektów.
Shailendra
3

Myślę, że pytanie jest nieco szersze i nie można go zredukować w adnotacjach w warstwie dostępu do danych. Musimy wziąć pod uwagę cały stos aplikacji, strategie transakcyjne, które chcemy zastosować i tak dalej. W serwisie IBM Developerworks znajduje się bardzo obszerny zbiór artykułów na ten temat autorstwa Marka Richardsa. Pierwszą znajdziesz tutaj: https://developer.ibm.com/articles/j-ts1/

Z poważaniem

dgiffone
źródło
2

Powinieneś użyć @Repositoryadnotacji

Dzieje się tak, ponieważ @Repositorysłuży do tłumaczenia Twojego niezaznaczonego wyjątku SQL na Spring Excpetion, a jedynym wyjątkiem, który powinieneś sobie poradzić, jestDataAccessException

danny.lesnik
źródło
10
Generalnie jest to prawdą w przypadku używania Springa, ale ponieważ repozytoria Spring Data są już obsługiwane przez proxy Spring - użycie @Repository nie robi żadnej różnicy.
Aleksander Blomskøld
0

Używamy również adnotacji @Transactional, aby zablokować rekord, aby inny wątek / żądanie nie zmieniły odczytu.

Zozo
źródło