Gdzie należy adnotacja @ Transactional?
Czy należy umieścić @Transactional
w DAO
klasach i/lub ich metodach, czy lepiej przypisać klasy usług, które wywołują za pomocą obiektów DAO? A może sensowne jest przypisywanie obu "warstw"?
19 answers
Myślę, że transakcje należą do warstwy usług. To ten, który wie o jednostkach pracy i przypadkach użycia. Jest to właściwa odpowiedź, jeśli masz kilka Dao wstrzykniętych do usługi, które muszą współpracować w jednej transakcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-03 12:23:49
Ogólnie zgadzam się z innymi stwierdzając, że transakcje są zwykle rozpoczynane na poziomie usługi(w zależności od szczegółowości, której oczywiście potrzebujesz).
Jednak w międzyczasie zacząłem również dodawać @Transactional(propagation = Propagation.MANDATORY)
do mojej warstwy DAO (i innych warstw, które nie mogą rozpoczynać transakcji, ale wymagają już istniejących), ponieważ znacznie łatwiej jest wykryć błędy w przypadku, gdy zapomniałeś rozpocząć transakcję w wywołującym (np. usłudze). Jeśli Twoje DAO jest opatrzone adnotacją obowiązkowa propagacja po wywołaniu metody zostanie wyświetlony wyjątek stwierdzający, że nie ma aktywnej transakcji.
Mam również test integracji, w którym sprawdzam wszystkie beans (Bean Post processor) pod kątem tej adnotacji i nie sprawdzam, jeśli w Beans, który nie należy do warstwy usług, jest adnotacja @Transactional
z propagacją inną niż obowiązkowa. W ten sposób upewniam się, że nie rozpoczynamy transakcji na niewłaściwej warstwie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-30 06:50:33
Adnotacje transakcyjne powinny być umieszczone wokół wszystkich nierozłącznych operacji.
Na przykład, Twoje wywołanie to "Zmień hasło". Składa się z dwóch operacji
- Zmień hasło.
- skontroluj zmianę.
- wyślij e-mail do klienta, że hasło zostało zmienione.
Więc w powyższym przypadku, jeśli audyt się nie powiedzie, to czy zmiana hasła również nie powinna? Jeśli tak, to transakcja powinna wynosić około 1 i 2 (tak w warstwie serwisowej). Jeśli e-mail fails (prawdopodobnie powinien mieć jakiś fail safe na to, aby nie zawieść) to powinien cofnąć zmianę hasła i audytu?
Są to pytania, które musisz zadać, decydując, gdzie umieścić @Transactional
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 06:46:26
Normalnym przypadkiem byłoby opisywanie na poziomie warstwy usług, ale tak naprawdę zależy to od twoich wymagań.
Adnotacja na warstwie usług spowoduje dłuższe transakcje niż adnotacja na poziomie DAO. W zależności od poziomu izolacji transakcji, które mogą youse problemy, jak równoczesne transakcje nie zobaczą siebie zmiany w np. POWTARZALNY ODCZYT.
Adnotacja na DAOs pozwoli utrzymać transakcje tak krótko, jak to możliwe, z wadą, że funkcjonalność twoja warstwa usług jest narażenie wont być wykonane w jednej (rollbackable) transakcji.
Nie ma sensu opisywać obu warstw, jeśli tryb propagacji jest ustawiony na domyślny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-03 12:45:41
Poprawną odpowiedzią dla tradycyjnych architektur Spring jest umieszczenie semantyki transakcyjnej na klasach usług, z powodów, które inni już opisali.
[[3]}rosnący trend na wiosnę jest w kierunku domain-driven design (DDD). wiosenne maleństwo ładnie ilustruje ten trend. Chodzi o to, aby obiekt domeny był dużo bogatszy niż na typowych architekturach wiosennych (zazwyczaj są to } anemiczne ), a w szczególności aby umieścić semantyka transakcji i trwałości samych obiektów domeny. W przypadkach, gdy potrzebne są tylko proste operacje CRUD, Kontrolery sieci Web działają bezpośrednio na POJOs obiektu domeny( w tym kontekście funkcjonują jako podmioty) i nie ma warstwy usług. W przypadkach, gdy potrzebna jest jakaś koordynacja między obiektami domeny, możesz mieć obsługę usługi, z@Transaction
zgodnie z tradycją. Możesz ustawić propagację transakcji w obiektach domeny na coś w stylu REQUIRED
tak, że obiekty domeny wykorzystują wszelkie istniejące transakcje, takie jak transakcje, które zostały rozpoczęte w usłudze bean.
Technicznie technika ta wykorzystuje AspectJ i <context:spring-configured />
. Roo używa definicji Inter-type AspectJ do oddzielenia semantyki encji (transactions i persistence) od obiektu domain (zasadniczo pól i metod biznesowych).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-21 10:14:07
Umieszczam @Transactional
na warstwie @Service
i ustawiam rollbackFor
dowolny wyjątek i readOnly
w celu dalszej optymalizacji transakcji.
Domyślnie @Transactional
będzie szukał tylko RuntimeException
(wyjątki niezaznaczone), ustawiając rollback na Exception.class
(wyjątki zaznaczone), będzie to rollback dla każdego wyjątku.
@Transactional(readOnly = false, rollbackFor = Exception.class)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-21 11:06:59
A może sensowne jest przypisywanie obu "warstw"? - czy nie ma sensu opisywać zarówno warstwy usług, jak i warstwy dao - jeśli ktoś chce mieć pewność, że metoda DAO jest zawsze wywoływana (propagowana) z warstwy usług z propagacją "obowiązkową" w DAO. Zapewniłoby to pewne ograniczenie wywoływania metod DAO z warstwy UI (lub kontrolerów). Również-w szczególności w przypadku jednostkowego testowania warstwy DAO-adnotacja DAO zapewni również, że jest ona testowana pod kątem transakcyjnym funkcjonalność.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-21 11:09:06
Ponadto Spring zaleca używanie adnotacji tylko na konkretnych klasach, a nie na interfejsach.
Http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-12 15:57:03
Dla transakcji na poziomie bazy danych
Najczęściej używałem @Transactional
w DAO tylko na poziomie metody, więc konfiguracja może być specjalnie dla metody / użycie domyślne (wymagane)
DAO ' s method that get data fetch (select .. )- nie trzeba
@Transactional
może to prowadzić do pewnych kosztów z powodu transaction interceptor / i AOP proxy, które muszą być wykonane jako cóż.Metody DAO, które robią insert / update otrzymają
@Transactional
Dla poziomu aplikacji -
Używam transakcji dla logiki biznesowej chciałbym być w stanie rolback w przypadku nieoczekiwanego błędu
@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){
try {
//service logic here
} catch(Throwable e) {
log.error(e)
throw new MyApplicationException(..);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-23 19:25:46
Zazwyczaj należy umieścić transakcję w warstwie usług.
Ale jak wspomniano wcześniej, atomiczność operacji mówi nam, gdzie potrzebna jest adnotacja. Tak więc, jeśli używasz frameworków takich jak Hibernate, gdzie pojedynczy " save/update/delete/...modyfikacja " operacja na obiekcie ma możliwość modyfikacji kilku wierszy w kilku tabelach (ze względu na kaskadę poprzez wykres obiektu), oczywiście na tym konkretnym DAO powinno być również zarządzanie transakcjami metoda.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-26 08:20:56
Lepiej mieć go w warstwie serwisowej! Jest to wyraźnie wyjaśnione w jednym z artykułów, które natknąłem się wczoraj! Oto link, który możesz sprawdzić!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-07 14:42:54
@Transactional
adnotacje powinny być umieszczone wokół wszystkich nierozłącznych operacji.
Obsługa propagacji transakcji @Transactional
automatically.In w tym przypadku, jeśli inna metoda zostanie wywołana bieżącą metodą, wtedy ta metoda będzie miała możliwość dołączenia do trwającej transakcji.
Więc weźmy przykład:
Mamy 2 modele tj. Country
i City
. Odwzorowanie relacyjne modelu Country
i City
jest takie, że jeden Country
może mieć wiele miast, więc mapowanie jest jak,
@OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;
Tutaj kraj mapowany do wielu miast z pobieraniem ich Lazily
. Pojawia się rola @Transactinal
gdy pobieramy obiekt Country z bazy danych, wtedy otrzymamy wszystkie dane obiektu Country, ale nie otrzymamy zestawu miast, ponieważ pobieramy miasta LAZILY
.
//Without @Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//After getting Country Object connection between countryRepository and database is Closed
}
Jeśli chcemy uzyskać dostęp do zestawu miast z obiektu country, wtedy otrzymamy wartości null w tym zestawie, ponieważ obiekt z zestawu utworzonego tylko ten zestaw nie jest inicjalizowany z danymi do uzyskania wartości Set używamy @Transactional
tj.
//with @Transactional
@Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal
Object object = country.getCities().size();
}
Więc zasadniczo @Transactional
is usługa może wykonać wiele połączeń w jednej transakcji bez zamykania połączenia z punktem końcowym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-27 12:05:41
Najpierw zdefiniujmy gdzie mamy użyć ?
Myślę, że prawidłowa odpowiedź brzmi - kiedy musimy upewnić się, że sekwencja działań zostanie zakończona razem jako jedna operacja atomowa lub nie nastąpi żadna zmiana, nawet jeśli jedna z akcji zawiedzie.
Powszechnie znaną praktyką jest wprowadzanie logiki biznesowej do usług. Tak więc metody usług mogą zawierać różne akcje, które muszą być wykonywane jako jedna logiczna jednostka pracy. Jeśli tak - to taka metoda musi być oznaczony jako . Oczywiście nie każda metoda wymaga takiego ograniczenia, więc nie trzeba oznaczać całej usługi jako transakcyjna.
I jeszcze więcej - nie zapomnij wziąć pod uwagę, że @ Transactional oczywiście może zmniejszyć wydajność metody. Aby zobaczyć cały obraz, musisz znać poziomy izolacji transakcji. Świadomość tego może pomóc ci uniknąć używania @ Transactional tam, gdzie nie jest to koniecznie potrzebne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-16 14:43:31
Warstwa usług jest najlepszym miejscem do dodawania adnotacji @Transactional
ponieważ większość logiki biznesowej tutaj obecnej zawiera zachowanie przypadków użycia na poziomie szczegółów.
Załóżmy , że dodamy go do DAO i z usługi wywołamy 2 klasy DAO , jedną nieudaną i drugą udaną, w tym przypadku jeśli @Transactional
nie na usłudze, jeden DB zostanie zatwierdzony, a drugi wycofany.
Dlatego zalecam mądrze używać tej adnotacji i używać tylko w warstwie serwisowej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-23 15:58:43
Idealnie, warstwa usług (Menedżer) reprezentuje Twoją logikę biznesową i dlatego powinna być opatrzona adnotacją @Transactional
.Warstwa usług może wywoływać różne DAO do wykonywania operacji DB. Przyjmijmy sytuacje, w których w metodzie usługowej jest N Liczba operacji DAO. Jeśli twoja pierwsza operacja DAO nie powiodła się, inne mogą być nadal przekazywane i skończysz jako niespójny stan DB. Adnotacja warstwy usługi może uchronić Cię przed takimi sytuacjami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-06 03:14:35
Wolę używać @Transactional
na warstwie usług na poziomie metod.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-06 03:14:46
@Transactional
używa w warstwie usług, która jest wywoływana za pomocą warstwy kontrolera (@Controller
) i warstwy usługi wywołania do warstwy DAO (@Repository
) tj. operacji związanych z bazą danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-06 03:15:07
The @Transactional
powinien być używany na warstwie usług, ponieważ zawiera logikę biznesową. Warstwa DAO ma zwykle tylko operacje CRUD bazy danych.
// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
Spring doc : https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-11 12:05:55
Lepiej trzymać @Transactional w oddzielnej warstwie środkowej między Dao a Service Layer. Ponieważ rollback jest bardzo ważny, możesz umieścić całą swoją manipulację DB w warstwie środkowej i zapisać logikę biznesową w warstwie usług. Warstwa środkowa będzie wchodzić w interakcje z warstwami DAO.
Pomoże Ci to w wielu sytuacjach, takich jak ObjectOptimisticLockingFailureException - ten wyjątek występuje dopiero po zakończeniu transakcji. Więc nie można go złapać w środku warstwa, ale możesz teraz złapać w warstwie serwisowej. Nie byłoby to możliwe, jeśli masz @Transactional w warstwie usług. Chociaż można złapać w kontrolerze, ale Kontroler powinien być tak czysty, jak to możliwe.
Jeśli wysyłasz pocztę lub sms w osobnym wątku po wykonaniu wszystkich opcji Zapisz, Usuń i zaktualizuj, możesz to zrobić w serwisie po zakończeniu transakcji w warstwie środkowej. Ponownie, jeśli wspomnisz @ Transactional w warstwie usług, poczta pójdzie nawet jeśli twój transakcja nie powiodła się.
Więc posiadanie warstwy middle @ Transaction pomoże uczynić Twój kod lepszym i łatwym w obsłudze. Inaczej, Jeśli używasz w warstwie DAO, możesz nie być w stanie cofnąć wszystkich operacji. Jeśli używasz w warstwie Usług, być może będziesz musiał użyć AOP(Aspect Oriented Programming) w niektórych przypadkach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-02 09:07:32