Należy umieścić @Transactional
w DAO
klasach i / lub ich metod czy też lepiej opisywanie klas usług, które są wzywające użyciu obiektów DAO? Czy ma sens dodawanie adnotacji do obu „warstw”?
java
spring
annotations
transactions
dao
Thomas Einwaller
źródło
źródło
Zasadniczo zgadzam się z innymi, stwierdzając, że transakcje zwykle rozpoczynane są na poziomie usługi (w zależności od wymaganej szczegółowości).
Jednak w międzyczasie zacząłem również dodawać
@Transactional(propagation = Propagation.MANDATORY)
do mojej warstwy DAO (i innych warstw, które nie mogą uruchamiać transakcji, ale wymagają już istniejących), ponieważ o wiele łatwiej jest wykryć błędy, w przypadku których zapomniałeś rozpocząć transakcję w abonencie wywołującym ( np. usługa). Jeśli Twoje DAO jest opatrzone adnotacją o obowiązkowej propagacji, otrzymasz wyjątek stwierdzający, że po wywołaniu metody nie ma żadnej aktywnej transakcji.Mam również test integracji, w którym sprawdzam wszystkie ziarna (postprocesor bean) pod kątem tej adnotacji i nie udaje się, jeśli istnieje
@Transactional
adnotacja z propagacją inną niż Obowiązkowa w fasoli, która nie należy do warstwy usług. W ten sposób upewniam się, że nie rozpoczynamy transakcji na niewłaściwej warstwie.źródło
@Transactional
klasę implementacji usługi i powinienem wdrożyć implementację klasy@Transactional(propagation = MANDATORY)
DAO (repozytorium)?Adnotacje transakcyjne należy umieszczać wokół wszystkich nierozdzielnych operacji.
Na przykład połączenie to „zmień hasło”. Składa się z dwóch operacji
Zatem w powyższym przypadku, jeśli audyt się nie powiedzie, to czy zmiana hasła również nie powiedzie się? Jeśli tak, to transakcja powinna wynosić około 1 i 2 (czyli w warstwie usługi). Jeśli wiadomość e-mail nie powiedzie się (prawdopodobnie powinna być w tym bezpieczna, aby nie zawiodła), to czy powinna wycofać hasło zmiany i audyt?
To są pytania, które musisz zadać, decydując, gdzie umieścić
@Transactional
.źródło
Prawidłową odpowiedzią dla tradycyjnych architektur Spring jest umieszczenie semantyki transakcyjnej w klasach usług z powodów, które inni już opisali.
Pojawiający się trend na wiosnę to projektowanie oparte na domenie (DDD). Spring Roo ładnie ilustruje ten trend. Chodzi o to, aby obiekt domeny POJO był znacznie bogatszy niż w typowych architekturach Spring (zwykle są one anemiczne ), a w szczególności, aby umieścić semantykę transakcji i trwałości na samych obiektach domeny. W przypadkach, gdy wszystko, czego potrzeba, to proste operacje CRUD, kontrolery sieciowe działają bezpośrednio na obiektach POJO obiektu domeny (w tym kontekście działają jako podmioty) i nie ma warstwy usług. W przypadkach, gdy potrzebna jest jakaś koordynacja między obiektami domeny, możesz obsłużyć komponent bean usługi za pomocą
@Transaction
zgodnie z tradycją. Można ustawić propagację transakcji na obiektach domenyREQUIRED
tak, aby obiekty domeny korzystały z wszelkich istniejących transakcji, takich jak transakcje rozpoczęte w komponencie bean usługi.Technicznie technika ta wykorzystuje AspectJ i
<context:spring-configured />
. Roo używa definicji typu AspectJ w celu oddzielenia semantyki encji (transakcji i trwałości) od elementów obiektu domeny (zasadniczo pól i metod biznesowych).źródło
Normalnym przypadkiem byłoby umieszczanie adnotacji na poziomie warstwy usługi, ale tak naprawdę zależy to od twoich wymagań.
Adnotacje w warstwie usług skutkują dłuższymi transakcjami niż adnotacje na poziomie DAO. W zależności od poziomu izolacji transakcji, który może powodować problemy, ponieważ transakcje współbieżne nie zobaczą nawzajem swoich zmian, np. POWTARZANE CZYTANIE.
Adnotacje na temat DAO sprawią, że transakcje będą jak najkrótsze, z tą wadą, że funkcjonalność, którą ujawnia twoja warstwa usług, nie będzie wykonywana w pojedynczej transakcji (możliwej do rozszerzenia).
Adnotacja na obu warstwach nie ma sensu, jeśli tryb propagacji jest ustawiony na domyślny.
źródło
Kładę
@Transactional
na@Service
warstwie i ustawiamrollbackFor
dowolny wyjątek oraz wreadOnly
celu dalszej optymalizacji transakcji.Domyślnie
@Transactional
będzie szukał tylkoRuntimeException
(Niezaznaczone wyjątki), ustawiając wycofywanie naException.class
(Sprawdzone wyjątki), będzie przywracał dla każdego wyjątku.Zobacz Sprawdzone vs. Niezaznaczone wyjątki .
źródło
Czy ma sens dodawanie adnotacji do obu „warstw”? - czy nie ma sensu adnotować zarówno warstwy usługi, jak i warstwy dao - jeśli chce się upewnić, że metoda DAO jest zawsze wywoływana (propagowana) z warstwy usługi z propagacją „obowiązkową” w DAO? Zapewniłoby to pewne ograniczenie dla wywoływania metod DAO z warstwy interfejsu użytkownika (lub kontrolerów). Ponadto - szczególnie w przypadku testowania jednostkowego warstwy DAO - adnotacja DAO zapewni również przetestowanie jej pod kątem funkcjonalności transakcyjnej.
źródło
propagation=Propagation.REQUIRES_NEW
. W przeciwnym razie w większości przypadków, w tym propagacji = obowiązkowe, DAO po prostu weźmie udział w istniejącej transakcji rozpoczętej przez warstwę usługi.Ponadto Spring zaleca stosowanie adnotacji tylko do konkretnych klas, a nie interfejsów.
http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
źródło
Do transakcji na poziomie bazy danych
głównie używałem
@Transactional
w DAO tylko na poziomie metody, więc konfiguracja może być specyficzna dla metody / przy użyciu domyślnej (wymagane)Metoda DAO, która pobiera dane (wybierz ..) - nie potrzebuje
@Transactional
tego, może prowadzić do narzutu z powodu przechwytywania transakcji / i proxy AOP, które również muszą zostać wykonane.Otrzymają metody DAO, które wstawiają / aktualizują
@Transactional
bardzo dobry blog o transakcjach
Na poziomie aplikacji -
używam transakcji dla logiki biznesowej Chciałbym mieć możliwość rolbacka w przypadku nieoczekiwanego błędu
źródło
Transactional
naJava
Zwykle transakcję należy umieścić w warstwie usługi.
Ale, jak powiedziano wcześniej, atomowość operacji mówi nam, gdzie adnotacja jest konieczna. Tak więc, jeśli używasz frameworków takich jak Hibernacja, w których pojedyncza operacja „zapisz / aktualizuj / usuń / ... modyfikacja” na obiekcie może potencjalnie zmodyfikować kilka wierszy w kilku tabelach (z powodu kaskady przez wykres obiektów) oczywiście powinno być również zarządzanie transakcjami dla tej konkretnej metody DAO.
źródło
@Transactional
Adnotacje należy umieszczać wokół wszystkich nierozdzielnych operacji. Korzystanie z@Transactional
propagacji transakcji jest obsługiwane automatycznie. W takim przypadku, jeśli inna metoda zostanie wywołana przez bieżącą metodę, wówczas ta metoda będzie miała opcję dołączenia do bieżącej transakcji.Weźmy więc przykład:
Mamy czyli 2 modelu
Country
iCity
. Mapowanie relacyjneCountry
iCity
model jest jakCountry
można mieć wiele Miast, więc mapowanie jest jak,Tutaj Kraj jest mapowany na wiele miast z ich pobieraniem
Lazily
. Więc tutaj pojawia się rola,@Transactinal
kiedy odzyskujemy obiekt Country z bazy danych, wtedy otrzymamy wszystkie dane obiektu Country, ale nie otrzymamy zbioru miast, ponieważ pobieramy miastaLAZILY
.Kiedy chcemy uzyskać dostęp do Zestawu Miast z obiektu kraju, wówczas otrzymamy wartości zerowe w tym Zestawie, ponieważ obiekt Zestawu utworzony tylko w tym Zestawie nie jest inicjowany z danymi tam, aby uzyskać wartości Zestawu, którego używamy,
@Transactional
tj.Zasadniczo
@Transactional
usługa może wykonywać wiele połączeń w jednej transakcji bez zamykania połączenia z punktem końcowym.źródło
@Transactional
naprawdę jestLepiej mieć go w warstwie serwisowej! Wyjaśnia to jasno jeden z artykułów, z którymi się wczoraj spotkałem! Oto link , który możesz sprawdzić!
źródło
@Transactional
Należy stosować na warstwie usługowej, ponieważ zawiera logikę biznesową. Warstwa DAO zwykle ma tylko operacje CRUD bazy danych.Dokument wiosenny: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html
źródło
Warstwa serwisowa jest najlepszym miejscem do dodawania
@Transactional
adnotacji, ponieważ większość logiki biznesowej jest tutaj dostępna, zawiera zachowanie przypadków użycia na poziomie szczegółów.Załóżmy, że dodajemy go do DAO, a z usługi nazywamy 2 klasy DAO, jedna nie powiodła się, a druga zakończyła się sukcesem, w tym przypadku, jeśli
@Transactional
nie jest w służbie, jedna baza danych zatwierdzi, a druga przywróci.Dlatego moim zaleceniem jest mądre stosowanie tej adnotacji i używanie jej tylko w warstwie serwisowej.
Projekt Github - java-algos
źródło
Przede wszystkim określmy, gdzie musimy użyć transakcji ?
Myślę, że poprawna odpowiedź brzmi - kiedy musimy upewnić się, że sekwencja akcji zostanie zakończona razem jako jedna operacja atomowa lub nie zostaną wprowadzone żadne zmiany, nawet jeśli jedna z akcji zakończy się niepowodzeniem.
Dobrze znaną praktyką jest wprowadzanie logiki biznesowej do usług. Metody serwisowe mogą więc zawierać różne działania, które muszą być wykonywane jako pojedyncza logiczna jednostka pracy. Jeśli tak, to taką metodę należy oznaczyć jako transakcyjną . Oczywiście nie każda metoda wymaga takich ograniczeń, więc nie musisz oznaczać całej usługi jako transakcyjnej .
Co więcej - nie zapomnij wziąć pod uwagę, że @Transactional może oczywiście obniżyć wydajność metody. Aby zobaczyć cały obraz, musisz znać poziomy izolacji transakcji. Wiedząc, że może to pomóc uniknąć korzystania z @Transactional tam, gdzie nie jest to konieczne.
źródło
Lepiej zachować @Transactional w oddzielnej środkowej warstwie między DAO a warstwą usług. Ponieważ wycofywanie jest bardzo ważne, możesz umieścić całą manipulację DB w środkowej warstwie i zapisać logikę biznesową w Warstwie usług. Środkowa warstwa będzie współdziałać z twoimi warstwami DAO.
Pomoże Ci to w wielu sytuacjach, takich jak ObjectOptimisticLockingFailureException - ten wyjątek występuje tylko po zakończeniu transakcji. Tak więc nie możesz złapać go w środkowej warstwie, ale możesz teraz złapać w warstwie usługi. Nie byłoby to możliwe, jeśli masz @Transactional w warstwie usługi. Chociaż możesz złapać kontroler, ale kontroler powinien być tak czysty, jak to możliwe.
Jeśli wysyłasz pocztę lub SMS-y w osobnym wątku po ukończeniu wszystkich opcji zapisywania, usuwania i aktualizacji, możesz to zrobić w usłudze po zakończeniu transakcji w warstwie środkowej. Ponownie, jeśli wspomnisz @Transactional w warstwie usług, poczta zostanie wysłana, nawet jeśli transakcja się nie powiedzie.
Posiadanie środkowej warstwy @Transaction pomoże uczynić kod lepszym i łatwiejszym w obsłudze. W przeciwnym razie, jeśli użyjesz w warstwie DAO, możesz nie być w stanie przywrócić wszystkich operacji. Jeśli używasz w warstwie usługi, w niektórych przypadkach może być konieczne użycie AOP (Programowanie zorientowane na aspekty).
źródło
Idealnie, warstwa usługowa (Manager) reprezentuje logikę biznesową i dlatego powinna być opatrzona adnotacjami z.
@Transactional
Warstwa serwisowa może wywoływać różne DAO w celu wykonywania operacji DB. Załóżmy sytuacje, w których masz N operacji DAO w metodzie usługi. Jeśli Twoja pierwsza operacja DAO zakończy się niepowodzeniem, inne mogą być nadal przekazywane i skończysz niespójnym stanem DB. Adnotacja Warstwa usługi może uchronić Cię przed takimi sytuacjami.źródło
Wolę używać
@Transactional
w warstwie usług na poziomie metody.źródło
@Transactional
wykorzystuje w warstwie usługi, która jest wywoływana przy użyciu warstwy kontrolera (@Controller
) i wywołania warstwy usługi do warstwy DAO (@Repository
), tj. operacji związanych z bazą danych.źródło