Próbuję użyć @Transational w metodzie, ale mam następujący problem. Najpierw jest to scenariusz:

1- Aktualizuję jego hasło

2- Wstawiam jego identyfikator do tabeli śledzenia (proste zapytanie wstawiania)

Aby przetestować moją transakcję, podaję istniejący identyfikator (klucz podstawowy) w zapytaniu wstawiającym.

Transakcja działa, ale otrzymuję ten błąd Transaction silently rolled back because it has been marked as rollback-only, wiedząc, że te dwie funkcje są wewnątrz bloku try-catch i normalnie powinien zwrócić Internal error.

Kiedy używam punktu przerwania w odpowiedzi, pokazuje internal error, ale w Postman otrzymuję Transaction silently rolled back because it has been marked as rollback-only.

To jest mój kod:

import javax.transaction.Transactional;

@Transactional
    public UpdateUserPasswordResponse updateUserPassword(String login, String pwd, String newPwd)
            throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException,
            UnsupportedEncodingException {

        GetUserByUsernameAndPasswordResponse responseLogin = new GetUserByUsernameAndPasswordResponse();

        UpdateUserPasswordResponse response = new UpdateUserPasswordResponse();

        // some code

        if (responseLogin.getUser() != null) {

//some code

            try {
                // call the update query from DAO
                int lineUpdated = dao.updateUserPassword(login, Cryptedpwd);


                int lineInserted = dao.insertUtilisateurTracking(responseLogin.getUser().getId(), new Date());

                response.setMessage(Constants.SUCCESS);
                response.setStatus(Constants.OK);

            } catch (Exception e) {

                response.setMessage(Constants.ERREUR_INTERNE);
                response.setStatus(Constants.KO);

            }
        } else {
            if (responseLogin.getMessage().equals(Constants.LOGIN_PASSWORD_INCORRECT)) {
                response.setStatus(Constants.KO);
                response.setMessage(Constants.LOGIN_PASSWORD_INCORRECT);
            } else {
                response.setMessage(Constants.ERREUR_INTERNE);
                response.setStatus(Constants.KO);
            }
        }

        return response;

    }
0
taha manar 19 grudzień 2019, 15:23
Oczywiście transakcja zostanie wycofana. Otrzymałeś dwa zapytania zapisu, jedno aktualizujące hasło, a drugie wprowadzające użytkownika. Pierwszy z nich jest wycofywany po awarii drugiego, ponieważ identyfikator użytkownika już istnieje. O ile nie chcesz innego zachowania, właśnie to zrobi dla Ciebie adnotacja @Transactional.
 – 
Alain Cruz
19 grudzień 2019, 15:31
Więc nie ma możliwości wyświetlenia błędu wewnętrznego zamiast wyjątku transakcji ??
 – 
taha manar
19 grudzień 2019, 15:45
Hmmm spróbuj dodać następujący @Transactional(rollbackFor = Exception.class). Ta siła, aby wycofać się tylko w przypadku zgłoszenia wyjątku, może działać, ale nie jesteś pewien.
 – 
Alain Cruz
19 grudzień 2019, 15:53

1 odpowiedź

Jest to normalne zachowanie, a powodem jest to, że metoda insertUtilisateurTracking wymaga TX podczas wykonywania. Ale kiedy jest wywoływana w metodzie updateUserPassword, dostępny jest TX, kontener nie tworzy nowego i wykorzystuje istniejący TX. Więc jeśli jakikolwiek wyjątek wystąpi w metodzie insertUtilisateurTracking, spowoduje to ustawienie TX na rollBackOnly (nawet jeśli złapiesz wyjątek w obiekcie wywołującym i zignorujesz go).

0
dassum 19 grudzień 2019, 15:36
Więc nie ma sposobu, aby pokazać Internal error zamiast wyjątku transakcji ??
 – 
taha manar
19 grudzień 2019, 15:44
Usuń blok wyjątku catch w metodzie updatePassword i użyj ExceptionHander, aby wysłać niestandardowy komunikat o błędzie. Sprawdź toptal.com/java/spring-boot-rest- obsługa błędów interfejsu API
 – 
dassum
19 grudzień 2019, 15:55