Wiosna @ Transactional - izolacja, propagacja

447

Czy ktoś może wyjaśnić, jakie są parametry izolacji i propagacji w @Transactionaladnotacji na przykładzie z prawdziwego świata?

Zasadniczo kiedy i dlaczego powinienem zmienić ich wartości domyślne.

Mat B.
źródło

Odpowiedzi:

442

Dobre pytanie, choć nie jest trywialne.

Propagacja

Określa relacje między transakcjami. Typowe opcje:

  • Required: Kod zawsze będzie działał w transakcji. Tworzy nową transakcję lub wykorzystuje ją ponownie, jeśli jest dostępna.
  • Requires_new: Kod zawsze będzie działał w nowej transakcji. Zawiesza bieżącą transakcję, jeśli taka istnieje.

Izolacja

Definiuje umowę danych między transakcjami.

  • Read Uncommitted: Pozwala na brudne odczyty.
  • Read Committed: Nie zezwala na brudne odczyty.
  • Repeatable Read: Jeśli wiersz zostanie odczytany dwukrotnie w tej samej transakcji, wynik zawsze będzie taki sam.
  • Serializable: Wykonuje wszystkie transakcje po kolei.

Różne poziomy mają różne parametry wydajnościowe w aplikacji wielowątkowej. Myślę, że jeśli zrozumiesz dirty readspojęcie, będziesz mógł wybrać dobrą opcję.


Przykład wystąpienia brudnego odczytu:

  thread 1   thread 2      
      |         |
    write(x)    |
      |         |
      |        read(x)
      |         |
    rollback    |
      v         v 
           value (x) is now dirty (incorrect)

Tak więc rozsądnym ustawieniem domyślnym (jeśli można tak twierdzić) może być Read Committedtylko odczytanie wartości, które zostały już zatwierdzone przez inne uruchomione transakcje, w połączeniu z poziomem propagacji wynoszącym Required. Następnie możesz pracować stamtąd, jeśli Twoja aplikacja ma inne potrzeby.


Praktyczny przykład tego, gdzie nowa transakcja będzie zawsze tworzona przy wchodzeniu do provideServicerutyny i zakończona przy wychodzeniu:

public class FooService {
    private Repository repo1;
    private Repository repo2;

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void provideService() {
        repo1.retrieveFoo();
        repo2.retrieveFoo();
    }
}

Gdybyśmy skorzystali zamiast tego Required, transakcja pozostałaby otwarta, gdyby transakcja była już otwarta podczas wprowadzania procedury. Należy również zauważyć, że wynik a rollbackmoże być inny, ponieważ kilka egzekucji może brać udział w tej samej transakcji.


Możemy łatwo zweryfikować zachowanie za pomocą testu i zobaczyć, jak wyniki różnią się w zależności od poziomów propagacji:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/fooService.xml")
public class FooServiceTests {

    private @Autowired TransactionManager transactionManager;
    private @Autowired FooService fooService;

    @Test
    public void testProvideService() {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        fooService.provideService();
        transactionManager.rollback(status);
        // assert repository values are unchanged ... 
}

Z poziomem propagacji wynoszącym

  • Requires new: spodziewalibyśmy się, że NIEfooService.provideService() został wycofany, ponieważ stworzył własną sub-transakcję.

  • Required: spodziewalibyśmy się, że wszystko zostało wycofane, a sklep z podkładami pozostał niezmieniony.

Johan Sjöberg
źródło
Jak ten ostatni link odnosi się do tego, o czym mówisz? Według powiązanych dokumentów, wydaje się, że sesja określa aktualną transakcję, a nie fabryka sesji.
Donal Fellows,
@Donal, o przepraszam, nie było jasne. Chodzi mi o to, że ponieważ sessionFactory.getCurrentTransaction()został dodany, nie trzeba HibernateTemplatejuż uruchamiać zarządzania transakcjami. Usunąłem go :)
Johan Sjöberg,
Moje pytanie dotyczyło tylko tego, gdzie wskazuje link. :-)
Donal Fellows,
jak uzyskać zmiany dokonane w bieżącej transakcji
Prasanna Kumar HA
304

PROPAGATION_REQUIRED = 0 ; Jeśli DataSourceTransactionObject T1 jest już uruchomiony dla metody M1. Jeśli dla innej metody M2 wymagany jest obiekt transakcji, nie jest tworzony nowy obiekt transakcji. Dla obiektu M2 używany jest ten sam obiekt T1

PROPAGATION_MANDATORY = 2 ; Metoda musi działać w ramach transakcji. Jeśli żadna istniejąca transakcja nie jest w toku, zostanie zgłoszony wyjątek

PROPAGATION_REQUIRES_NEW = 3 ; Jeśli DataSourceTransactionObject T1 jest już uruchomiony dla metody M1 i jest w toku (wykonywanie metody M1). Jeśli inna metoda M2 zacznie działać, wówczas T1 zostanie zawieszony na czas metody M2 z nowym DataSourceTransactionObject T2 dla M2.M2 uruchomionym w ramach własnego kontekstu transakcji

PROPAGATION_NOT_SUPPORTED = 4 ; Jeśli DataSourceTransactionObject T1 jest już uruchomiony dla metody M1. Jeśli inna metoda M2 jest uruchomiona jednocześnie. Następnie M2 nie powinien działać w kontekście transakcji. T1 jest zawieszony do czasu ukończenia M2.

PROPAGATION_NEVER = 5 ; Żadna z metod nie działa w kontekście transakcji.

Poziom izolacji: Chodzi o to, jak duży wpływ na transakcję mogą mieć działania innych równoczesnych transakcji. Zapewnia spójność, pozostawiając dane w wielu tabelach w spójnym stanie. Polega na blokowaniu wierszy i / lub tabel w bazie danych.

Problem z wieloma transakcjami

Scenariusz 1. Jeżeli transakcja T1 odczytuje dane z tabeli A1, która została zapisana przez inną równoległą transakcję T2, jeżeli w drodze wycofywania T2 dane otrzymane przez T1 są nieprawidłowe, np. Dane a = 2 są danymi oryginalnymi. Jeśli T1 odczytał a = 1, który został napisany przez T2. Jeśli wycofanie T2, a = 1 zostanie cofnięte do a = 2 w DB, ale teraz T1 ma a = 1, ale w tabeli DB jest zmienione na a = 2.

Scenariusz 2. Jeśli transakcja T1 odczytuje dane z tabeli A1. Jeśli inna transakcja równoległa (T2) aktualizuje dane w tabeli A1. Następnie dane odczytane przez T1 różnią się od tabeli A1. Ponieważ T2 zaktualizowało dane w tabeli A1. przeczytaj a = 1 i T2 zaktualizowane a = 2. Następnie a! = b.

Scenariusz 3. Jeżeli transakcja T1 odczytuje dane z tabeli A1 z określoną liczbą wierszy. Jeśli inna jednoczesna transakcja (T2) wstawi więcej wierszy w tabeli A1. Liczba wierszy odczytanych przez T1 różni się od wierszy w tabeli A1

Scenariusz 1 nosi nazwę Brudne odczyty.

Scenariusz 2 nazywa się odczytami niepowtarzalnymi.

Scenariusz 3 nosi nazwę Odczyty fantomowe.

Zatem poziom izolacji to zakres, w którym można zapobiec Scenariuszowi 1, Scenariuszowi 2, Scenariuszowi 3 . Całkowity poziom izolacji można uzyskać, stosując blokowanie. Zapobiega to jednoczesnemu odczytywaniu i zapisywaniu tych samych danych, ale wpływa na wydajność. Poziom izolacji zależy od aplikacji wymaganej izolacji.

ISOLATION_READ_UNCOMMITTED : Pozwala odczytać zmiany, które nie zostały jeszcze zatwierdzone. Dotyczy scenariusza 1, scenariusza 2, scenariusza 3

ISOLATION_READ_COMMITTED : Pozwala na odczyty z jednoczesnych transakcji, które zostały zatwierdzone. Może to dotyczyć scenariusza 2 i scenariusza 3. Ponieważ inne transakcje mogą aktualizować dane.

ISOLATION_REPEATABLE_READ : Wiele odczytów tego samego pola da te same wyniki, dopóki nie zostanie zmienione samodzielnie. Może to mieć wpływ na Scenariusz 3. Ponieważ inne transakcje mogą wstawiać dane

ISOLATION_SERIALIZABLE : Scenariusz 1, Scenariusz 2, Scenariusz 3 nigdy się nie zdarza. Jest to całkowita izolacja. Obejmuje pełne blokowanie. Ma zdolność wykonywania z powodu blokowania.

Możesz przetestować za pomocą

public class TransactionBehaviour {
   // set is either using xml Or annotation
    DataSourceTransactionManager manager=new DataSourceTransactionManager();
    SimpleTransactionStatus status=new SimpleTransactionStatus();
   ;


    public void beginTransaction()
    {
        DefaultTransactionDefinition Def = new DefaultTransactionDefinition();
        // overwrite default PROPAGATION_REQUIRED and ISOLATION_DEFAULT
        // set is either using xml Or annotation
        manager.setPropagationBehavior(XX);
        manager.setIsolationLevelName(XX);

        status = manager.getTransaction(Def);

    }

    public void commitTransaction()
    {


            if(status.isCompleted()){
                manager.commit(status);
        } 
    }

    public void rollbackTransaction()
    {

            if(!status.isCompleted()){
                manager.rollback(status);
        }
    }
    Main method{
        beginTransaction()
        M1();
        If error(){
            rollbackTransaction()
        }
         commitTransaction();
    }

}

Możesz debugować i zobaczyć wynik z różnymi wartościami izolacji i propagacji.

abishkar bhattarai
źródło
jak uzyskać zmiany dokonane w bieżącej transakcji
Prasanna Kumar HA
2
Jaka jest interakcja między poziomem izolacji a propagacją ? Jeśli metoda 1 rozpoczyna transakcję z poziomem izolacji, powiedzmy READ_COMMITTED, a później wywołuje metodę 2 z poziomem REPEATABLE_READ, z pewnością metoda 2 musi zostać wykonana we własnej nowej transakcji, niezależnie od tego, jakie zachowanie propagacyjne określa (np. WYMAGANE)?
Cornel Masson
Na koncert jest już naprawdę późno, ale kiedy PROPAGATION_REQUIRES_NEW, co stanie się z T1 (używanym przez M1), jeśli kolejne nowe połączenie nastąpi z M1? (powiedz M1.1)
Tim Z.
115

Wystarczające wyjaśnienie każdego parametru podano w innych odpowiedziach; Jakkolwiek prosiłeś o przykład z prawdziwego świata, oto ten, który wyjaśnia cel różnych opcji propagacji :

Załóżmy, że jesteś odpowiedzialny za wdrożenie usługi rejestracji, w której użytkownik otrzymuje wiadomość e-mail z potwierdzeniem. Pojawiają się dwa obiekty usługowe, jeden do rejestracji użytkownika i jeden do wysyłania wiadomości e-mail, który ten drugi nazywany jest wewnątrz pierwszego. Na przykład coś takiego:

/* Sign Up service */
@Service
@Transactional(Propagation=REQUIRED)
class SignUpService{
 ...
 void SignUp(User user){
    ...
    emailService.sendMail(User);
 }
}

/* E-Mail Service */
@Service
@Transactional(Propagation=REQUIRES_NEW)
class EmailService{
 ...
 void sendMail(User user){
  try{
     ... // Trying to send the e-mail
  }catch( Exception)
 }
}

Być może zauważyłeś, że druga usługa ma typ propagacji REQUIRES_NEW, a ponadto istnieje prawdopodobieństwo, że zgłasza wyjątek (wyłączenie serwera SMTP, nieprawidłowa wiadomość e-mail lub inne przyczyny). Prawdopodobnie nie chcesz, aby cały proces był wycofywany, np. usuwanie informacji o użytkowniku z bazy danych lub innych rzeczy; dlatego wywołujesz drugą usługę w oddzielnej transakcji.

Wracając do naszego przykładu, tym razem martwisz się bezpieczeństwem bazy danych, więc zdefiniuj swoje klasy DAO w ten sposób:

/* User DAO */
@Transactional(Propagation=MANDATORY)
class UserDAO{
 // some CRUD methods
}

Oznacza to, że za każdym razem, gdy tworzony jest obiekt DAO, a tym samym potencjalny dostęp do db, musimy zapewnić, że połączenie zostało wykonane z jednej z naszych usług, co oznacza, że ​​transakcja na żywo powinna istnieć; w przeciwnym razie wystąpi wyjątek, dlatego propagacja jest typu OBOWIĄZKOWA .

ye9ane
źródło
26
Idealny przykład dla REQUIRES_NEW.
Ravi Thapliyal
5
Dobre wytłumaczenie! Przy okazji, jakie jest domyślne ustawienie dla propagacji? Byłoby jeszcze lepiej, gdybyś mógł podać taki przykład również dla izolacji. Wielkie dzięki.
Prakash K
5
@PrakashK Domyślnie jest WYMAGANE. ( docs.spring.io/spring-framework/docs/current/javadoc-api/org/… )
ihebiheb
59

Poziom izolacji określa, w jaki sposób zmiany wprowadzone w niektórych repozytoriach danych przez jedną transakcję wpływają na inne jednoczesne transakcje, a także w jaki sposób i kiedy te zmienione dane stają się dostępne dla innych transakcji. Kiedy definiujemy transakcję za pomocą frameworka Spring, jesteśmy również w stanie skonfigurować, na jakim poziomie izolacji ta sama transakcja zostanie wykonana.

@Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {

}

Poziom izolacji READ_UNCOMMITTED stwierdza, że ​​transakcja może odczytać dane, które są nadal niezatwierdzone przez inne transakcje.

Poziom izolacji READ_COMMITTED stwierdza, że ​​transakcja nie może odczytać danych, które nie zostały jeszcze zatwierdzone przez inne transakcje.

Poziom izolacji REPEATABLE_READ stwierdza, że ​​jeśli transakcja odczytuje jeden rekord z bazy danych wiele razy, wynik wszystkich tych operacji odczytu musi być zawsze taki sam.

SERIALIZABLE poziom izolacji jest najbardziej restrykcyjnym ze wszystkich poziomów izolacji. Transakcje są wykonywane z blokowaniem na wszystkich poziomach (blokowanie odczytu, zakresu i zapisu), dzięki czemu wydają się być wykonywane w sposób szeregowy.

Propagacja to zdolność do decydowania o tym, w jaki sposób metody biznesowe powinny być zawarte w logicznych lub fizycznych transakcjach.

Zachowanie WYMAGANE na wiosnę oznacza, że ​​ta sama transakcja zostanie użyta, jeśli istnieje już otwarta transakcja w bieżącym kontekście wykonania metody komponentu bean.

Zachowanie REQUIRES_NEW oznacza, że ​​kontener zawsze tworzy nową fizyczną transakcję.

Zachowanie NESTED powoduje, że zagnieżdżone transakcje sprężynowe używają tej samej transakcji fizycznej, ale ustawia punkty zapisu między zagnieżdżonymi wywołaniami, aby transakcje wewnętrzne mogły również być wycofywane niezależnie od transakcji zewnętrznych.

Zachowanie OBOWIĄZKOWE stwierdza, że ​​istniejąca otwarta transakcja musi już istnieć. Jeśli nie, wyjątek zostanie zgłoszony przez kontener.

Zachowanie NIGDY nie stanowi, że istniejąca otwarta transakcja nie może już istnieć. Jeśli istnieje transakcja, kontener zgłosi wyjątek.

Zachowanie NOT_SUPPORTED zostanie wykonane poza zakresem jakiejkolwiek transakcji. Jeśli otwarta transakcja już istnieje, zostanie ona wstrzymana.

Zachowanie WSPIERA zostanie wykonane w zakresie transakcji, jeśli otwarta transakcja już istnieje. Jeśli nie ma już otwartej transakcji, metoda zostanie wykonana mimo wszystko w sposób nietransakcyjny.

reos
źródło
4
Gdybyś mógł dodać, kiedy użyć, który byłby o wiele bardziej korzystny.
Kumar Manish
Podaj przykłady, Byłoby to bardzo pomocne dla początkujących
nitinsridar
23

Transakcja reprezentuje jednostkę pracy z bazą danych.

W TransactionDefinitioninterfejsie wiosennym , który definiuje właściwości transakcji zgodne ze sprężyną. @Transactionaladnotacja opisuje atrybuty transakcji w metodzie lub klasie.

@Autowired
private TestDAO testDAO;

@Transactional(propagation=TransactionDefinition.PROPAGATION_REQUIRED,isolation=TransactionDefinition.ISOLATION_READ_UNCOMMITTED)
public void someTransactionalMethod(User user) {

  // Interact with testDAO

}

Rozmnażanie (reprodukcja): służy do relacji między transakcjami. (analogicznie do komunikacji między wątkami Java)

+-------+---------------------------+------------------------------------------------------------------------------------------------------+
| value |        Propagation        |                                             Description                                              |
+-------+---------------------------+------------------------------------------------------------------------------------------------------+
|    -1 | TIMEOUT_DEFAULT           | Use the default timeout of the underlying transaction system, or none if timeouts are not supported. |
|     0 | PROPAGATION_REQUIRED      | Support a current transaction; create a new one if none exists.                                      |
|     1 | PROPAGATION_SUPPORTS      | Support a current transaction; execute non-transactionally if none exists.                           |
|     2 | PROPAGATION_MANDATORY     | Support a current transaction; throw an exception if no current transaction exists.                  |
|     3 | PROPAGATION_REQUIRES_NEW  | Create a new transaction, suspending the current transaction if one exists.                          |
|     4 | PROPAGATION_NOT_SUPPORTED | Do not support a current transaction; rather always execute non-transactionally.                     |
|     5 | PROPAGATION_NEVER         | Do not support a current transaction; throw an exception if a current transaction exists.            |
|     6 | PROPAGATION_NESTED        | Execute within a nested transaction if a current transaction exists.                                 |
+-------+---------------------------+------------------------------------------------------------------------------------------------------+

Izolacja: Izolacja jest jedną z właściwości ACID (Atomowość, Spójność, Izolacja, Trwałość) transakcji w bazie danych. Izolacja określa, w jaki sposób integralność transakcji jest widoczna dla innych użytkowników i systemów. Używa do blokowania zasobów, tj. Kontroli współbieżności, upewnij się, że tylko jedna transakcja może uzyskać dostęp do zasobu w danym punkcie.

Postrzeganie blokady: poziom izolacji określa czas trwania blokady.

+---------------------------+-------------------+-------------+-------------+------------------------+
| Isolation Level Mode      |  Read             |   Insert    |   Update    |       Lock Scope       |
+---------------------------+-------------------+-------------+-------------+------------------------+
| READ_UNCOMMITTED          |  uncommitted data | Allowed     | Allowed     | No Lock                |
| READ_COMMITTED (Default)  |   committed data  | Allowed     | Allowed     | Lock on Committed data |
| REPEATABLE_READ           |   committed data  | Allowed     | Not Allowed | Lock on block of table |
| SERIALIZABLE              |   committed data  | Not Allowed | Not Allowed | Lock on full table     |
+---------------------------+-------------------+-------------+-------------+------------------------+

Czytaj postrzeganie: występują następujące 3 rodzaje głównych problemów:

  • Dirty reads : odczytuje nieprzypisane dane z innej transmisji (transakcji).
  • Niepowtarzalne odczyty : odczyty popełnione UPDATESz innego tx.
  • Phantom czyta : czyta popełnione INSERTSi / lub DELETESz innego tx

Poziomy izolacji z różnymi rodzajami odczytów:

+---------------------------+----------------+----------------------+----------------+
| Isolation Level Mode      |  Dirty reads   | Non-repeatable reads | Phantoms reads |
+---------------------------+----------------+----------------------+----------------+
| READ_UNCOMMITTED          | allows         | allows               | allows         |
| READ_COMMITTED (Default)  | prevents       | allows               | allows         |
| REPEATABLE_READ           | prevents       | prevents             | allows         |
| SERIALIZABLE              | prevents       | prevents             | prevents       |
+---------------------------+----------------+----------------------+----------------+

dla przykładów

Premraj
źródło
20

Prawie nigdy nie chcesz używać, Read Uncommitedponieważ nie jest tak naprawdę ACIDzgodny. Read Commmitedjest dobrym domyślnym miejscem początkowym. Repeatable Readjest prawdopodobnie potrzebny tylko w scenariuszach raportowania, zestawienia lub agregacji. Zauważ, że wiele baz danych, w tym postgres, w rzeczywistości nie obsługuje powtarzalnego odczytu, musisz Serializablezamiast tego użyć . Serializablejest przydatny w przypadku rzeczy, o których wiesz, że muszą się zdarzyć całkowicie niezależnie od wszystkiego innego; pomyśl o tym jak synchronizedw Javie. Serializowalność idzie w parze z REQUIRES_NEWpropagacją.

Używam REQUIRESdo wszystkich funkcji, które uruchamiają zapytania UPDATE lub DELETE, a także funkcji poziomu usług. W przypadku funkcji poziomu DAO, które uruchamiają tylko SELECT, używam, SUPPORTSktóra będzie uczestniczyć w TX, jeśli jest już uruchomiona (tj. Wywołana z funkcji serwisowej).

AngerClown
źródło
13

Izolacja transakcji i propagacja transakcji, chociaż są powiązane, ale wyraźnie są to dwie bardzo różne koncepcje. W obu przypadkach wartości domyślne są dostosowywane w komponencie granicy klienta za pomocą Deklaratywnego zarządzania transakcjami lub Programowego zarządzania transakcjami . Szczegóły dotyczące każdego poziomu izolacji i atrybutów propagacji można znaleźć w odnośnikach poniżej.

Izolacja transakcji

W przypadku danych dwóch lub więcej działających transakcji / połączeń z bazą danych, jak i kiedy zmiany dokonywane przez zapytania w jednej transakcji wpływają / są widoczne dla zapytań w innej transakcji. Odnosiło się to również do tego, jakiego rodzaju blokowanie rekordów bazy danych zostanie wykorzystane do odizolowania zmian w tej transakcji od innych transakcji i odwrotnie. Zazwyczaj jest to realizowane przez bazę danych / zasób uczestniczący w transakcji.

.

Propagacja transakcji

W aplikacji korporacyjnej dla dowolnego żądania / przetwarzania istnieje wiele komponentów, które są zaangażowane w wykonanie zadania. Niektóre z tych komponentów oznaczają granice (początek / koniec) transakcji, która będzie używana w odpowiednim komponencie i jego podskładnikach. W przypadku tej granicy transakcyjnej komponentów Propogacja transakcji określa, czy dany komponent będzie uczestniczył w transakcji, a co się stanie, jeśli wywołujący komponent już ma lub nie ma już utworzonej / uruchomionej transakcji. Jest to to samo, co atrybuty transakcji Java EE. Zazwyczaj jest to realizowane przez menedżera transakcji / połączeń klienta.

Odniesienie:

Gladwin Burboz
źródło
1
Świetnie, Wszystkie informacje w jednym miejscu, Linki są bardzo pomocne, Dziękuję @Gladwin Burboz
nitinsridar
7

Mam biegać outerMethod, method_1a method_2w trybie innym propagacji.

Poniżej przedstawiono dane wyjściowe dla innego trybu propagacji.

  • Metoda zewnętrzna

    @Transactional
    @Override
    public void outerMethod() {
        customerProfileDAO.method_1();
        iWorkflowDetailDao.method_2();
    }
  • Metoda_1

    @Transactional(propagation=Propagation.MANDATORY)
    public void method_1() {
        Session session = null;
        try {
            session = getSession();
            Temp entity = new Temp(0l, "XXX");
            session.save(entity);
            System.out.println("Method - 1 Id "+entity.getId());
        } finally {
            if (session != null && session.isOpen()) {
            }
        }
    }
  • Metoda 2

    @Transactional()
    @Override
    public void method_2() {
        Session session = null;
        try {
            session = getSession();
            Temp entity = new Temp(0l, "CCC");
            session.save(entity);
            int i = 1/0;
            System.out.println("Method - 2 Id "+entity.getId());
        } finally {
            if (session != null && session.isOpen()) {
            }
        }
    }
      • outerMethod - Bez transakcji
      • method_1 - Propagacja. OBOWIĄZKOWE) -
      • method_2 - Tylko adnotacja transakcji
      • Dane wyjściowe: metoda_1 zgłasza wyjątek, że nie ma żadnej transakcji
      • outerMethod - Bez transakcji
      • method_1 - Tylko adnotacja transakcji
      • method_2 - Propagation.MANDATORY)
      • Dane wyjściowe: metoda_2 zgłosi wyjątek, że żadna istniejąca transakcja
      • Dane wyjściowe: metoda_1 zachowa zapis w bazie danych.
      • outerMethod - Z transakcją
      • method_1 - Tylko adnotacja transakcji
      • method_2 - Propagation.MANDATORY)
      • Dane wyjściowe: metoda_2 zachowa zapis w bazie danych.
      • Dane wyjściowe: metoda_1 zachowa zapis w bazie danych. - Tutaj główna transakcja zewnętrzna istniejąca stosowana zarówno dla metody 1, jak i 2
      • outerMethod - Z transakcją
      • method_1 - Propagacja. OBOWIĄZKOWE) -
      • method_2 - Tylko adnotacja transakcji i zgłasza wyjątek
      • Dane wyjściowe: brak zapisu w bazie danych oznacza wycofanie.
      • outerMethod - Z transakcją
      • method_1 - Propagacja.REQUIRES_NEW)
      • method_2 - Propagation.REQUIRES_NEW) i zgłasza wyjątek 1/0
      • Dane wyjściowe: metoda_2 zgłosi wyjątek, aby rekord metody_2 nie został zachowany.
      • Dane wyjściowe: metoda_1 zachowa zapis w bazie danych.
      • Dane wyjściowe: Nie ma wycofania dla metody_1
NIrav Modi
źródło
3

Możemy dodać do tego:

@Transactional(readOnly = true)
public class Banking_CustomerService implements CustomerService {

    public Customer getDetail(String customername) {
        // do something
    }

    // these settings have precedence for this method
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void updateCustomer(Customer customer) {
        // do something
    }
}
Ankit
źródło
1

Możesz użyć w ten sposób:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public EventMessage<ModificaOperativitaRapporto> activate(EventMessage<ModificaOperativitaRapporto> eventMessage) {
//here some transaction related code
}

Możesz użyć tej rzeczy również:

public interface TransactionStatus extends SavepointManager {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    void flush();
    boolean isCompleted();
}
Ankit
źródło