witam,
mam nastepujacy problem: mam metode w singleton beanie ktory jest oznaczona transaction not_supported. ta metoda pobiera liste encji z bazy danych i wrzuca je na liste. nastepnie iterujac po tej liscie kazdy element jest edutowany i zapisywany do bazy, a rownoczesnie wysylany na kolejke. z kolejki odbiera ten obiekt inny system i go oddaje. po oddaniu moj system(operacja w singletonie wciaz trwa) zupelnie inna metoda odbiera dane z kolejki, pobiera obiekt z bazy(ta sama tabela co w singletonie) i elegancko go edytuje. i teraz zagadka ktorej nie rozumiem: poza pisie po odebraniu z kolejki w bazie widze stan jaki chcialbym zobaczyc, jednak kiedy singleton skonczy iterowac po petli to wychodzac z metody obiekty zapisuja sie przez zabrudzenie ze stanem przed trafieniem na kolejke.. jak to mozliwe? przeciez tam nie ma transakcji?
Transakcje to są zawsze, wbij to sobie do głowy. Bazy danych sie na nich opierają i KAŻDA operacja w bazie danych jest objęta transakcją. To że ty sobie ręcznie transakcją z poziomu javy nie zarządzasz znaczy tyle że SZBD sam o to zadba i pewnie będzie transakcja per operacja albo coś w tym stylu.
no wlasnie chyba nie do konca.. tutaj dziala jakis magiczny mechanizm/architektura EJB. mamy blizniaczy mechanizm w springu.. ten sam kod praktycznie ale kontenerem jest spring i taka sytuacja nie ma miejsca. zreszta gdyby tak bylo to by oznaczalo ze w sytuacji kiedy wykonuje sie dlugotrwala operacja ale juz na samym poczaku przestaje korzystac z obiektu to i tak do czasu zakonczenia calej dlugotrwalej metody nikt inny obiektu nie moze wyedytowac.. a tak nie jest
Bzdury i mity. To że ty nie znasz innej metody synchronizacji niż blokowanie rekordów to nie znaczy że twórcy SZBD ich nie znają. Zaręczam ci że nic blokować nie trzeba. A ja bym się właśnie takiego efektu spodziewał jak ten który opisałeś, bo tak by wynikało z uszeregowania transakcji.
okej a moze jakas rada jak to zalatwic?
Pierwsze co przychodzi do głowy to zadbanie o to żeby nie edytować jednocześnie z dwóch miejsc tych samych rekordów, bo to się dobrze nie skończy.
no i to jest racja ale sie nie da tego wyeliminowac. a uproscmy troche te sytuacje: mam metode nietrasakcyjna(not_supported) pobralem liste encji z bazy i sobie zmieniam wlasciwosci tego obiektu. nie robie fizycznie edycji na bazie.. a moja metoda po zakonczeniu wciaz wysyla te obiekty do bazy.. sama:/ dlaczego?
A jesteś pewny że dzieje się tak jak napisałeś? Bo ja mam jednak wątpliwości. Sytuacja z twojego pierwszego posta wyląda inaczej: wygląda jakbyś miał jeszcze jakąś transakcje "wyżej" i to ona jest przyczyną twoich problemów.
BTW nie pojmuje czemu kombinujesz z wyłączeniem transakcji w sytuacji kiedy piszesz do bazy (!) i czytasz licząc na spójne dane...
odpowiedz jest bardzo prosta.. to jest task ktory wykonuje sie cyklicznie(anotacja schedule w EJB). i teraz jesli na ktorym elemencie z listy poleci mi wyjatek to ja chce to zalogowac a nie cofac cala transakcje czyli kazda iteracja w petli po elementach ma sie wykonac niezaleznie. czy jestem pewien ...tak. chyba ze ejb zaklada jakas transakcje magiczna o ktorej nie wiem - to mozliwe, ale nawet jesli to z opisu not_supported wynika ze moja metoda powinna miec to w nosie
Nie bardzo rozumiem co ma tutaj wyjątek i logowanie błędu do cofania transakcji. Przecież możesz wyjątek złapać i zalogować i tyle. Transakcja się wycofa dopiero gdybyś wyskoczył z metody tego EJB za pomocą wyjątku.
no chyba niekoniecznie.. jesli poleci np z innego serwisu ten wyjatek to cala tranzakcja zostanie oznaczona jako rollback i juz jest koniec. ale to nie jest meritum sprawy.. chcialbym poznac powod czemu w mojej architekturze dzieje sie to co opisalem a ten sam kod w springu dziala inaczej.
Albo co w springu działa inaczej? Przecież Spring nie implementuje EJB. Za pomocą czego dokonujesz w tym springu operacji na bazie danych?
za pomoca dokladnie tego samego co w ejb czyli hibernate. dlatego zakladam ze roznica wynika w saym dzialaniu kontenera (spring vs ejb) a nie w sposobie obslugi bazy. moze chodzi o jakas transakcje ejb niezwiazana z sama baza tylko np nie wiem.. z obiektami w pamieci? no generalnie koncza mi sie pomysly.. pewnie czegos nie wiem i jest to prostte do wyjasnienia.. nie daje mi to spokoju
Aaaa no paaanie to pisz po ludzku co robisz w tym kodzie. Szklana kula mi się zabrudziła...
Sprawa jest prosta: jeśli jest aktywna sesja hibernate to następuje automatyczne commitowanie zmian w obiektach. Więc jeśli pobrałeś sobie Session i masz je cały czas otwarte i dokonujesz zmian w obiektach encyjnych które za pomocą tego Session wyciągałeś to te obiekty będą automatycznie miały robione saveOrUpdate() nawet jeśli sam go nie wywołasz.
no ale wciaz sie pojawia zapytanie.. czemy to dziala inaczej w ejb i w spring. no i teraz.. moze da sie je jakos odpiac w ejb od tej sesji? w sumie jak tak sobie mysle to musze jutro sprawdzic czy przypadkiem nie zamykamy jawnie sesji w aplikacji ze springiem.. bo mozliwe ze tak jest i to by wyjasnialo sprawe. a jak to zrobic w ejb? dodam ze w ejb korzystamy raczej z czystego jpa a jako implementacji uzywamy wlasnie hibernate. nie uzywamy sesji z hibernate tylko entity managera z jpa. masz moze jakis pomysl?
Kwestia czy to JPA czy goły Hibernate nie gra tu wielkiej roli. Ot otwarty EntityManager = otwarte Session.
A jak wyglądaja transakcje u ciebie w tym Springu? Bo tam przecież nie możesz nie mieć otwartej transakcji bo sie posypie. Zgaduje że masz tam transakcje na odczyt danych a potem ją kończysz (i tym samym zamykasz sesje). W EJB za to nie masz transakcji na tej metodzie EJB, ale znów skoro ciągniesz dane z JPA to tam musi być jakaś transakcja, więc zgaduje że twoja metoda EJB robi to co powinna, czyli "zawiesza" tą transakcję i wykonuje operacje poza transakcją, ale sesja jest otwarta więc po odwieszeniu merguje sobie zmiany.
no i pewnie wlasnie tak jest.. bo operacje w metodzie od razu widac na bazie.. ale po wyjsciu z niej tak jak mowisz emerguje zmiany.. no i w 99% przypadkow nie ma z tym problemu bo i tak jawnie zapisalem zmiany ale w tym konkretnym przypadku nie moge do tego dopuscic.. wiec pytanie brzmi.. jak jawnie w tym ejb mam zamknac sesje na entity managerze?
Ja bym zrobił detach() na tych obiektach ;)
czyli po edycji na kazdym po prostu detach i bedzie ok? jutro to przetestuje i dam znac;)
Jak zrobisz detach() to entitymanager nie powinien tych zmian mergować.
Ale ja nadal trochę nie ogarniam tej twojej logiki którą tu stosujesz. Bo po co w ogóle ten singleton modyfikuje obiekty skoro potem chcesz te modyfikacje olać i zachować te modyfikacje z kolejki?
okej to szybkie wprowadzenie.. mamy 3 stany obiektu: waiting , in_progress, done. singleton wciage waitingi i ustawia je na in_progress i pcha na kolejke. inny system wciaga z kolejki i jesli poprawnio obsluzyl to mi odsyla i mowi ze skonczyl wiec powinienem ustawic done. no i problem byl taki ze nawet jesli ustawilem done to moj singleton(@schedule) przez zabrudzenie zapisywal z powrotem in_progress. no i cala filozofia:)
Ale ja w takim razie nie rozumiem w ogóle tych cudów na kiju z jakimiś transakcjami lewymi. Singleton pobiera sobie listę, robi ładny update za pomocą hqla / jpqla jednym zapytaniem, commituje te zmiany i wrzuca w kolejke (bo rozumiem że updatowałeś to rekord po rekordzie i było za wolno i dlatego chciałeś od razu po jednym obiekcie wrzucać do kolejki?). Scheduler wyciąga z kolejki i sie bawi. W czym problem?
Albo lepiej: po co w ogóle ten singleton? Czemu scheduler sam po wyciągnięciu obiektu nie ustawia mu in_progress a potem nie zmienia na done?
scheduler wrzuca na kolejke ustawiajac na inprogress i leci dalej z kolejnymi obiektami.. kolejka dziala niezaleznie i zmienia sobie obiekt w bazie na done. poniewaz scheduler dziala dluzej niz pojedyncza operacja zmiany na done.. to po wyjsciu nadpisuje zmiany swoim inprogress.. prosciej nie umiem wyjasnic:P moze daloby sie to zrobic prosciej ale takiego rozwiazania wymagala architektura wszystkich naszych systemow a to juz zupelnie inny temat.. wk azdym razie jhestem praktycznie przekonany ze odpiecie obiektu z otwartej sesji zalatwi sprawe. jutro dam znac:)
ok wyglada na to ze detach zadzialal. dzieki za pomoc. ale jest cieka2wostka: detach musi byc wywolany dokladnie w tym samym serwisie w ktory zostal zrobiony find. czesc operacji delegujemy do innego serwisu i tam odpiecie nie zadzialalo!
A czemu miałoby niby zadziałać? W tym innym serwisie za pewne te obiekty nie są już podpięte po prostu ;] Przecież jak je zserializujesz i z deserializujesz, albo wyjdziesz poza ramy transakcji / sesji to odpięcie jest automatyczne.
Nawet gdybyś tych obiektów nie odpiął, to zapewne żadna ze zmian wprowadzonych w tym drugiej serwisie nie zostałaby "automatycznie mergowana".
no pewnie masz racje:) w kazdym raize wiekszy temat:) ja zawsze utozsamialem transakcje z se4sja a jednak okazuje sie ze to bylo duzym bledem:)
Ehhh a ze zwykłym SQL nie byłoby takich problemów :)
to akurat swieta racja:P ale co zrobisz.. kazda technologia niesie swoje zasaday, z ktorymi nie warto walczyc. te akurat maja swoj zawily sens:)