Készítek egy saját bean validátort (jsr-303), ami az insertnél futna le és ellenőrizné, hogy a megadott felhasználónévvel létezik-e már user. A Validation Class-ba, ezért beinjektáltam egy EJB service-t, melyet meghívok és visszaadna, egy true vagy false értéket. A problémám az, ha a servicem az EntityManager find metódusát hívja meg, akkor mivel a Validation a persist meghívása után hívódik automatikusan, ezért az EM cacheből vissza adja saját magát, hogy igen már létezik, persze csak a validation lefutása után létezhetne valójában a db-ben is. Ezért próbálkoztam Hibernate NamedQuery-vel, ott megadható a cachelés (CacheModeType), viszont így betöltésnél, lefuttatná a betöltött Entitásra is a validációt és így egy végtelen ciklusba kerül. Próbáltam a persistence.xml javax.persistence.validation.group.pre-update és javax.persistence.validation.group.pre-persist-hez group-ot és a validátoromhoz is groupot rendelni, de nem segített. Persze megoldhatnám másképp is ezt a dolgot, de a jsr-303-at pont ezért találták ki. Ahol elakadtam: Az EM find-ra nem lehet valahogy kikapcsolni a cachelést? (Bár ez Hibernate NamedQuery-vel úgy néz ki megoldódott) A Query lefutására nem lehetne valahogy kikapcsolni a validációt?
9 Comments
Simon László
Közben jött egy ötlet, hogy mi lenne, ha a TransactionAttributeType-ot átállítanám a service-ben? Bejött! Ez lett a megoldás.
Auth Gábor
Az ember néha már azzal sokat segít magán, ha megfogalmazza a problémát...
Viczián István
Azt hadd kérdezzem már meg, hogy miért a persist után hívódik meg a validation? Nem úgy kéne működnie, ha nem érvényes egy entitás, akkor nem is próbálod beszúrni?
Simon László
Lehet félreértettél, vagy rosszul írtam. nem persist után, hanem persist alatt hívódik meg.
Nekem a debug szerint úgy működik, hogy az Entitymanager persist metódusa után bekerül az EntityManager cache-be és a persist persze hívja/futtatja a validátorokat, de az egyik Validatoromba be kellett injektáljak egy EJB bean-t(mellyel lekérdezem, hogy létezik-e már a usernév), mely kezdetben megörökölte a tranzakció vezérlést és ezáltal az Entitymanager cache-t is a persist-et hívó EJB-től és ez volt a problémám, hogy hiába ellenőrizte a Validator EJB-m find-al, hogy létezik-e, mert a cache-ben ott volt amire még nem futott le a tranzakció, így mindig azt dobta, hogy létezik.
Viczián István
Csodás, ennek tényleg így kell működnie. Csak kíváncsiság miatt érdekelne, hogy mi lenne, ha tennél egy olyan feltételt is bele, hogy ahol az id nem egyelő a perzisztálni kívánt entitás id-jával. Vagy ilyenkor még nem is ad neki id-t, és így teszi a cache-be? Vagy ha ad neki, de elbukik a validáció, akkor ugrott az az id?
Simon László
Igen, igazad van, erre is gondoltam... utólag... de amikor az entitásokat terveztem, úgy gondoltam, hogy lehet a loginname unique, így nincs id-m. Egyébként egy másik projektemben pont így vizsgálok egyediséget, ahogy leírtad. Pont ezért gondoltam, hogy "helytakarékosság" miatt nem lesz id-m
Auth Gábor
Mostanság egy 4-8 bájtos id mező nem igazán segít a helytakarékosságban... ellenben sokat segít, ha van...
Simon László
Hát igen, csak arra is gondoltam, hogy ha nekem a loginname lenne az id-m, akkor nem kell indexelnem, hanem mivel id, automatikusan indexelt. Míg, ha nem az lenne, akor külön kellene indexelni. Nem nagy különbségek, ízlések és pofonok...
jah, és így em.find()-ot használhatok kersésre, nem kell semmi hókuszpók. De ez se akkora nagy feature/elöny, de mégis valami
Simon László
lenne egy olyan kérdésem is, hogy szeretném a Hibernate OGM-et glassfish alá Cassandra-val bekonfigurálni. 3 féle képpen próbálkoztam:
1, Felveszem a persistence-unit-ot a persistence xml-be és a @PersistenceContext-el berántom, ahol kell. Ennél ott akadtam el, hogy nem tudom, hogyan kell NoSQL-es pool-t a glassfishbe bekonfigolni. Gondolom a lib-je alá kell tenni a hector-t, mint driver-t és valahol megadni a pool adatait, node hol? Gondolom nem a jdbc alarr, de akkor Connectors vagy a Resource Adapters alatt? Vagy kellen írjak valami saját modul-t glassfish alá, ami betölti?
2, próbálkoztam a Persistence.createEntityManagerFactory-val és gondoltam ahova teszek egy @Inject-et, oda CDI-al beteszi majd ezt a @Singletone Entitymanager-t. Node elfelejtettem, hogy ugye a Glassfish alatt ő manageli az adatforrásokat, így a createEntityManagerFactory-ra kaptam egy szép exception-t.
3, Hát végül nem OGM, hanem sima hector... A logika megegyezik a 2-es ponttal, csak @Inject-re a a hector-al felépített EntityManagert kézzel hozom létre a hector new EntitymanagerImpl-el.
A kérdés inkább az elsőre vonatkozik csak, hogy hogyan lehetne a glassfisht felkonfgolni, hogy az OGM persistence-unit-ot @PersistenceContext-el betöltse?