brak rollbacku

Odpowiedz Nowy wątek
2018-12-08 21:37
0

Dlaczego to mi nie rollbackuje xD . Uprościłem tę metodę maksymalnie tylko po to żeby zobaczyć czy kiedy mi wyrzuci runtime exception(po dodaniu drugiej wizyty o tym samym czasie) to wywala błąd ale mimo to nie cofa z bazy danych i mam exception "Visits with such date already with database" i status 500 a mimo to w bazie danych zostaje ta krotka

@EnableTransactionManagement
@Transcational
@Service
            public class VisitService {

                private final static Logger logger = LoggerFactory.getLogger(VisitService.class);

                private final VisitRepository visitRepository;

                public VisitService(VisitRepository visitRepository) {
                    this.visitRepository = visitRepository;
                }

                public List<Visit> findAllByDate(LocalDateTime date){

                    return  visitRepository.findAllByDate(date);
                }

                @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRED)
                public Visit save(@Valid Visit visit) {
                    logger.info("Inside visitService");
                    visit.setPayed(false);
                    if (visit.getPrice().intValue() > 1000)
                        visit.setDiscount(new BigDecimal(0.05));
                    else visit.setDiscount(new BigDecimal(0.00));

                    visitRepository.save(visit);
                    if(findAllByDate(visit.getDate()).size()>1)
                        throw new RuntimeException();

                    return  null;

                }

            }

istotna cześć stack trace'a

2018-12-08 23:16:23.653 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
Hibernate: insert into visits (visit_date, description, discount, payed, pet_id, price, vetid) values (?, ?, ?, ?, ?, ?, ?)
2018-12-08 23:16:23.663 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2018-12-08 23:16:23.664 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAllByDate]
Hibernate: select visit0
.id as id16, visit0_.visit_date as visit_da26, visit0_.description as descript36, visit0_.discount as discount46, visit0_.payed as payed56, visit0_.pet_id as pet_id66, visit0_.price as price76, visit0_.vet_id as vet_id86 from visits visit0 where visit0.visit_date=?
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAllByDate]
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.samples.petclinic.services.VisitService.save] after exception: java.lang.RuntimeException
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.RuleBasedTransactionAttribute : Applying rules to determine whether transaction should rollback on java.lang.RuntimeException
2018-12-08 23:16:23.685 TRACE 3360 --- [nio-8080-exec-2] o.s.t.i.RuleBasedTransactionAttribute : Winning rollback rule is: RollbackRuleAttribute with pattern [java.lang.RuntimeException]
2018-12-08 23:16:23.690 DEBUG 3360 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Failed to complete request: java.lang.RuntimeException
2018-12-08 23:16:23.698 ERROR 3360 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException] with root cause

java.lang.RuntimeException: null

edytowany 7x, ostatnio: masterkwi, 2018-12-09 00:20

Pozostało 580 znaków

2018-12-09 11:29
0

DataSource z autocomitem ?

Nie wiem jak mogę to przestawić jeśli to faktycznie to. Używam spring5 MVC i jestem nowicjuszem ;/ Ja używam spring data - masterkwi 2018-12-09 11:40

Pozostało 580 znaków

2018-12-09 12:07
1

Pewnie masz transakcję na każdym save którą jest od razu commitowana. Czy używasz JpaRepository? jeżeli tak to by się zgadzało.
Pokaż kod VisitRepository.

Edit: po logach widzę że to JpaRepository
Możesz spróbować dać enableDefaultTransactions = false w @EnableJpaRepositories. To wyłączy transakcje na metodach JpaRepository i pozwoli samemu ustawiać @Transactional tam gdzie się chce. Trzeba pamiętać że to ustawienie globalne.

edytowany 3x, ostatnio: Seti87, 2018-12-09 12:19

Pozostało 580 znaków

2018-12-09 12:49
0

Znowu komuś magia nie działa. Dziwne, nie?

Transakcja w JPARepository nie ma znaczenia, bo przecież ta zewnętrzna (VisitService.save) jest propagowana( a raczej powinna być).
(btw. te wszystkie parametry (isolation = Isolation.READ_COMMITTED, rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRED) możesz sobie odpuścić).
Dlaczego nie jest?
Nie widzę błędu w tym kawałku kodu, pokaż jak wywołujesz VisitService.save, tam chyba jest jakiś kanał.
I w ogóle dziwne jest to @EnableTransactionManagement... korzystasz ze springboot ? Bo jeśli nie to ta adnotacja jest w złym miejscu (co może powodować twój problem). Jeśli korzystasz ze springboot ... to jest niepotrzebna.


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
edytowany 2x, ostatnio: jarekr000000, 2018-12-09 12:51
korzystam ze spring boota. Czytałem w dokumentacji że to potrzebne - masterkwi 2018-12-09 13:29

Pozostało 580 znaków

2018-12-09 14:01
0
Seti87 napisał(a):

Pewnie masz transakcję na każdym save którą jest od razu commitowana. Czy używasz JpaRepository? jeżeli tak to by się zgadzało.
Pokaż kod VisitRepository.

Edit: po logach widzę że to JpaRepository
Możesz spróbować dać enableDefaultTransactions = false w @EnableJpaRepositories. To wyłączy transakcje na metodach JpaRepository i pozwoli samemu ustawiać @Transactional tam gdzie się chce. Trzeba pamiętać że to ustawienie globalne.


public interface VisitRepository extends Repository<Visit, Integer> {

    Visit save(Visit visit);

    List<Visit> findByPetId(Integer petId);

    Visit findById(Integer visitId);

    @Transactional(readOnly = true)
    List<Visit> findAllByDate(LocalDateTime date);

    Visit findByDate(LocalDateTime date);

}
Przetestowałeś to o czym pisałem? - Seti87 2018-12-09 15:18
tak, to działa krotka znika. Minusem jest tylko to że zaczęły mi się teraz pojawiać inne błędy w web serwise xD. To znaczy że wszędzie gdzie mam teraz zapisywanie i działanie na bazie danych muszę dopisać @Transactional, bo inaczej nie działa? Chociaż w sumie nie rozumiem dlaczego na samym początku to nie działało z defaultowego poziomu? Wielkie dzięki dobry człowieku :) Poczytałem o tym i błędów ubywa, ale bez ciebie to bym nie ruszył z miejsca ;) - masterkwi 2018-12-09 15:25
Za szybko przytaknąłem jednak krotka nie znika, ale projekt przesłałem na githuba - masterkwi 2018-12-09 16:43
A nie doałeś @Transactional na całe VisitRepository? bo w przykładzie wyżej go nie było a w projekcie na githubie jest. Ustawienie enableDefaultTransactions = false było własnie po to żeby na repozytorium nie mieć bezpośrednio żadnych @Transactional domyślnie ustawionych przez spring data. Dodając @Transactional na VisitRepository włączyłeś na nowo to co wyłączyło "enableDefaultTransactions = false". - Seti87 2018-12-09 16:48

Pozostało 580 znaków

2018-12-09 14:57
0

Ale po co transactional w Repository to ja nie wiem


Nie pomagam przez PM. Pytania zadaje się na forum.

Pozostało 580 znaków

2018-12-09 15:13
0
scibi92 napisał(a):

Ale po co transactional w Repository to ja nie wiem

Tzn tam było dziwne zachowanie. Za pewne to dlatego że czegoś nie rozumiem ale w momencie kiedy robiłem findAll to w bazie danych pojawiała się dana, więc dla pewności dodałem flage że to do odczytu ale to i tak nic nie dało i za każdym razem kiedy robiłem findAll to wtedy właśnie przed save pojawiała już w bazie danych ;/

Pozostało 580 znaków

2018-12-09 15:52
0

Nie możesz pokazać całości kodu? Jak dla mnie za dużo coś kombinujesz...


Nie pomagam przez PM. Pytania zadaje się na forum.
Ok, pokaże - masterkwi 2018-12-09 15:59

Pozostało 580 znaków

2018-12-09 16:42
0
scibi92 napisał(a):

Nie możesz pokazać całości kodu? Jak dla mnie za dużo coś kombinujesz...

https://github.com/CharlesCZ/problem

Nie musisz cytowac poprzedniego postu... Chyba że odnościsz się do fragmentu - scibi92 2018-12-09 16:50

Pozostało 580 znaków

2018-12-09 16:54
0

@masterkwi: Ty ten serwis wywołujesz tylko z poziomu VisitControllera? W takim razie wywal wszystkie transactionale z niekontrolerów i daj znać :D

poza tym to @EnableJpaTransactional (czy jakoś tak) powinno być w klasie z adnotacja @Configuration


Nie pomagam przez PM. Pytania zadaje się na forum.
edytowany 1x, ostatnio: scibi92, 2018-12-09 16:56
Zrobiłem tak jak mówisz: pousuwałęm zbędne @Transactional, ale nie mogłem dać @Transactional na cały kontroller bo wywalało mi błąd że mi transakcja commitowała przy samym gecie kiedy ściągałem formularz. Dodałem też osobny config . Wstawiłem na githuba kod - masterkwi 2018-12-09 17:08
No i jaki jest skutek? - scibi92 2018-12-09 17:15
Krotka nadal jest w bazie danych - masterkwi 2018-12-09 17:33

Pozostało 580 znaków

2018-12-09 21:02
3

Wyjaśnienie jest takie, że zapisujesz zupełnie gdzie indziej.

A dokładnie to tu (VisitController):

@ModelAttribute("visit")
    public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
        System.out.println("wywolanie modelAttribute!!!!!!!!!!!!!");
        Pet pet = this.pets.findById(petId);
        model.put("pet", pet);
        Visit visit = new Visit();
        pet.addVisit(visit); //I tu następuje katastrofa - (K)
        return visit;
    }

Katastrofa (K) występuje, albowiem w Pet masz :

 @OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.EAGER)
  private Set<Visit> visits = new LinkedHashSet<>();

Cascade ALL spowoduje, że dodanie visit (do Pet) spowoduje jej zapisanie (kaskadowo). Nieważne, że potem robisz save w (VisitService.save) (niepotrzebnie...).

Możesz spradzić, że usunięcie linii visitRepository.save(visit); nic nie zmienia. Katastrofa była już wcześniej. A metody twojego tak zwanego kontrolera nie mają @Transactional, więc wszystko wpada do bazy.


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
edytowany 2x, ostatnio: jarekr000000, 2018-12-09 21:04

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0