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"?

Author: Thomas Einwaller, 2009-07-03

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.

 462
Author: duffymo,
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.

 268
Author: mnp,
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

  1. Zmień hasło.
  2. skontroluj zmianę.
  3. 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.

 76
Author: Michael Wiles,
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.

 37
Author: hammarback,
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).

 37
Author: Willie Wheeler,
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)

Zobacz zaznaczone vs. niezaznaczone wyjątki.

 29
Author: user2601995,
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ść.

 17
Author: tweekran,
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

 15
Author: davidemm,
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)

  1. 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óż.

  2. Metody DAO, które robią insert / update otrzymają @Transactional

Bardzo dobry blog on

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(..);
    }
}
 13
Author: lukass77,
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.

 12
Author: yannick555,
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ć!

 7
Author: sundary,
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.

 5
Author: Harshal Patil,
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.

 4
Author: smaiakov,
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.

Github project-java-algos

 3
Author: VishalTambe,
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.

 2
Author: salsinga,
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.

 1
Author: Spark-Beginer,
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.

 1
Author: Satish Suradkar,
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

Tutaj wpisz opis obrazka

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

 1
Author: Alin,
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.

 0
Author: Nabin Kumar Khatiwada,
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