2012. július 8., vasárnap

JPA több szálon

No, 2 napig izzadtam a JPA-val, mire működésre bírtam, de tanulságos volt.

Szituáció: van 2 táblám, közöttük 2 db N-M kapcsolat (az egyik önmagával). A multithreaded crawler-em pakolja bele a rekordokat, amit a JPA "Duplicate entry" hibaüzenettel jutalmaz. Pedig igyekeztem szinkronizáltan hívogatni a persist-et, meg a find-ot. De nem eléggé, mert entity osztályonként volt csak szinkronizált. Ha rákeresünk a gugliban, azt találjuk, hogy az EntityManager-t egy szálból illik használni.

Viszont nekem több szálam van, és szükségem lenne a tárolásra és lekérdezésre futás közben.

Tehát: meg kell oldani, hogy az EntityManager-hez, de azon belül is a persist-hez egyszerre csak egy szál férhessen hozzá.

Én a következőt csináltam (persze leegyszerűsített példa):

Van egy Storage osztályom, ahol statikusan van tárolva az EM, és a következő statikus és szinkronizált (!!!) metódusai vannak:

  • void store(Object o)
  • Object getInstanceFor(Class c, Object pk)


A store nyit egy tranzakciót, persist, commit.

A getInstanceFor a find funkcionalitását toldja meg azzal, hogy ha nincs ilyen entitás, akkor létrehozza és el is tárolja, persze a store-ral.

A szálak a getInstaceFor-t hívják lelkesen, néha a store-t is. Azzal, hogy a persist csak egy helyen szerepel, és csak szinkronizáltan hívható, biztosítom azt, hogy egy időpillanatban maximum egyetlen szál raktároz el valamit az adatbázisban.

Persze nyilván van ennél jobb módszer is. :-)

Nincsenek megjegyzések: