Blokowanie metody @Transactional

Blokowanie metody @Transactional
M2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 lata
  • Postów:10
0

Siemka. Mam problem z dodaniem niektórych obiektów do bazy danych. Mam obiekt użytkownika, który zawiera obiekt @OneToOne, który jest skrzynką wiodomości. Istnieje w niej obiekt Set <Conversation> zawierający listę rozmów. Rozmowa zawiera informacje o sobie i liście obiektów List<Message>. Wiadomość zawiera kilka innych danych. Zrobiłem metodę oznaczoną jako @Transactional, która "tworzy nową wiadomość". Wykonuję w nim odpowiednie operacje, a następnie zapisuję dane w powyższych obiektach. Robię to w ten sposób:

Kopiuj
@Transactional
public Set<Conversation> newMessage(MessageHelper messageHelper) {
    User sender = userRepository.getUserByUserName(messageHelper.getFrom());
    User receiver = userRepository.getUserByUserName(messageHelper.getTo());

    Conversation senderConversation = conversationRepository.getConversationWithUser(sender.getUsername(), receiver.getUsername());
    if(senderConversation == null)
        senderConversation = new Conversation(sender.getUsername(), receiver.getUsername());

    Conversation receiverConversation = conversationRepository.getConversationWithUser(receiver.getUsername(), sender.getUsername());
    if(receiverConversation == null)
        receiverConversation = new Conversation(receiver.getUsername(), sender.getUsername());

    Message message = messageHelper.getMessage();
    receiverConversation.getMessages().add(message);

    Message receiverMessage = new Message(message.getMessageFrom(), message.getMessage());
    receiverMessage.setWhenSent(message.getWhenSent());
    senderConversation.getMessages().add(receiverMessage);

    sender.getMessageBox().getConversationList().add(senderConversation);
    receiver.getMessageBox().getConversationList().add(receiverConversation);

    entityManager.persist(message);
    entityManager.persist(receiverMessage);

    entityManager.merge(sender);
    entityManager.merge(receiver);


    Set<Conversation> conversations = getConversations(sender.getUsername());
    System.out.println("Conv from service: " + conversations);
    System.out.println(userRepository.getUserByUserName(sender.getUsername()));
    // the application hangs here
    return conversations;
}

Następnie chcę zwrócić konwersacje użytkownika po utworzeniu, aby zawierał aktualne dane po stronie klienta. Wszystko wydaje się być w porządku, wypisując w konsoli dane o konwersacji i użytkowniku jest wszystko ok, są również wszystkie id, nie są nullami, ale obiekt nie jest zwracany, a metoda zawiesza się i nie zwraca niczego bez rzucania wyjątku. Aplikacja kliencka oczekuje na odpowiedź z serwera, ale nic się nie dzieje, aplikacja serwera zawiesza się. Co ja robię źle?

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

NIe widze dlaczego się ma zawieszać, może powód jest na zewnątrz tego kodu, gdzie wywołujesz. To Spring i JPA? Dużo rzeczy może się wyrypać.
Ale najbardziej nie rozumiem po co:

Kopiuj
    entityManager.merge(sender);
    entityManager.merge(receiver);

Co ten kawałek kodu miał zrobić?


jeden i pół terabajta powinno wystarczyć każdemu
M2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 lata
  • Postów:10
0

Ogólnie myśl jest taka że wiadomość ląduje do skrzynki odbiorcy i nadawcy więc aktualizuje dane obu. Co do technologii to Spring Boot + Jpa. Jeśli chodzi o wywoływanie to raczej standardowo. Na Resta przychodzi obiekt, jest normalnie odczytywany itp. Dane po wykonaniu metod entityManager'a też wyświetlam żeby się upewnić i są ok. Sam właśnie nie wiem co może być nie tak.

Jak coś to dodaje logi od insertów z trybu debugowania:

Kopiuj
2018-09-28 13:47:58.447 DEBUG 10476 --- [nio-8090-exec-1] org.hibernate.SQL                        : insert into message (is_readed, message, message_from, when_sent, id) values (?, ?, ?, ?, ?)
2018-09-28 13:47:58.449 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIT] - [false]
2018-09-28 13:47:58.450 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [aaaaaaa]
2018-09-28 13:47:58.450 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [mati]
2018-09-28 13:47:58.451 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [TIMESTAMP] - [Fri Sep 28 13:47:57 CEST 2018]
2018-09-28 13:47:58.452 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [BIGINT] - [785]
2018-09-28 13:47:58.454 DEBUG 10476 --- [nio-8090-exec-1] org.hibernate.SQL                        : insert into message (is_readed, message, message_from, when_sent, id) values (?, ?, ?, ?, ?)
2018-09-28 13:47:58.455 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIT] - [false]
2018-09-28 13:47:58.455 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [aaaaaaa]
2018-09-28 13:47:58.455 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [mati]
2018-09-28 13:47:58.455 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [TIMESTAMP] - [Fri Sep 28 13:47:57 CEST 2018]
2018-09-28 13:47:58.455 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [BIGINT] - [786]
2018-09-28 13:47:58.467 DEBUG 10476 --- [nio-8090-exec-1] org.hibernate.SQL                        : insert into message_box_conversation_list (message_box_id, conversation_list_id) values (?, ?)
2018-09-28 13:47:58.467 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [674]
2018-09-28 13:47:58.467 TRACE 10476 --- [nio-8090-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [BIGINT] - [721]

Nie powiem, że jestem orłem w tych technologiach bo wprawdzie dopiero zaczynam ale na moje oko to tak wygląda jakby dane były dodane "wstępnie" ale cała transakcja nie została zakończona i jest przez coś blokowana.

edytowany 1x, ostatnio: mati220
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

Nadal nie wyjaśniłes po co te dwie linijki.

Jak transakcja wisi - touzyj narzędzi odpowiednich do twojej bazy danych i sprawdź na czym wisi.


jeden i pół terabajta powinno wystarczyć każdemu
M2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 lata
  • Postów:10
0

Dodałem po to by pobrane wcześniej obiekty zaktualizować.
Apropos to Set<Conversation> i List<Message> są oparte na @ElementCollection jakby coś.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

I sądziesz, że te wywołania (u Ciebie) coś aktualizują? Masz to z jakiejś książki czy coś?
Edit: nie sprawdziłeś w bazie na czym to wisi?
Mozesz dodac przed retutn jeszcze entityManager.flush() jak sie na tym zawiesi, to mniej wiecej wiadomo, że masz blokade na bazie.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 2x, ostatnio: jarekr000000
M2
Jeśli dodam flush() przed to faktycznie się blokuje nie wypisując tego co jest niżej.
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:5 dni
  • Postów:2370
0

Pomijając tego merga, to @Transactional skąd masz?

M2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 lata
  • Postów:10
0

Nie sądzę i nie mam szczerze mówiąc :D Jedynie wcześniej robiąc podobne rzeczy w ten sposób dawało to wymierne korzyści więc tutaj też tak zrobiłem. Ogólnie to jak wcześniej pisałem orłem w tym nie jestem więc mogę nie wiedzieć dokładnie jak coś działa.

@yarel
Początkowo z javax.transaction.Transactional potem org.springframework.transaction.annotation.Transactional ale efekt ten sam.

edytowany 1x, ostatnio: mati220
Zobacz pozostały 1 komentarz
YA
No i zamiast zgadywać, to może pokazałbyś stosy: narzędzie jps -> wylistuj PIDy procesów javowych i jstack, żeby zrzucić stosy wątków.
M2
Niee :D po prostu chciałem sprawdzić inną opcją czy będzie ten sam efekt. Normalnie miałem z pakietu javax.
M2
Ok, muszę najpierw ogarnąć jak w ogóle tego używać bo szczerze mówiąc to nie miałem nawet styczności z tym więc wiesz :)
YA
jps - pokazuje Ci listę pidów procesów JVM i wybierasz ten Twój serwer (możesz zweryfikować np. ps aux | grep pid, czy to faktycznie ten), zaś jstack <pid> robi zrzut stosów wszystkich wątków w ramach procesu JVM
jarekr000000
A do tego jak twoja baza nie jest tajna i nie jest w strefie 51 to na pewno ma narzędzie do podejrzenia aktualnie wykonywanych transakcji, blockad.
M2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 lata
  • Postów:10
0

Hmmm nie wiem jak ale uruchomiłem od nowa laptopa (pewnie przy okazji się baza danych uruchomiła na nowo) i wszystko działa :D
W każdym razie dziękuje Wam za pomoc :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.