JPA @GeneratedValue összetett kulcs

Fórumok

Sziasztok!

Adott a következő probléma:
Van egy entitás melynek összetett elsődleges kulcsa van.


create table project(
	id integer,
	id_mod integer,
            ….
)

Az id_mod mező a project „verziókezeléséhez” kellene.
Tehát ha rögzítésre kerül az adat akkor mondjuk

(1,1)

lesz a kulcs értéke, viszont ha projekt entitás bizonyos mezői változnak és mentésre kerül akkor keletkezzen egy új rekord a táblában de már

(1,2)

kulccsal, tehát ne updatelje a meglévő sort hanem insertáljon egy újat.

Ha csak egy mező a kulcs akkor a JPA egész jó támogatást ad a kezeléséhez a

@GeneratedValue

és társai segítségével.
A fenti problémához nyújt valami támogatást?

Hozzászólások

Ha a @Version annotáció nem elégséges, akkor Hibernate @EmbeddedId illetve @IdClass irányba nézelődnék, bár az nem derült ki, hogy Hibernate elérhető-e.

Jelenleg EclipseLink van használatban.

De lehet megtévesztő voltam ezzel a "verziókezelés" szóhasználattal.
Inkább egy másik pédával szemléltetném mit szeretnék elérni.

Nézünk egy tipikus webáruházat vagy inkább egy számlát.

Van ugye

vevo(id, nev, adoszam)

és a

szamla_fej(id, id_vevo)

tábla.

Ha a

szamla_fej

táblában nem tárolod el a vevő nevét és adószámát, csak hivatkozol rá, de menet közben megváltozik valemlyik adat, akkor ha a régi számlákat megtekinted, akkor ott is az új nevet és/vagy adószámot fogod látni, ami ugye nem jó mert a számla keletkezésének pillanatában nem az volt.

Na most
- vagy eltárolod ezeket a mezőket a

szamla_fej

táblában, de akkor elég nagyra fog hízni az adatbázis
- ha megváltozik valamelyik adat akkor mint új vevőt felviszed újra de, az sem jó mert mégis csak ugyan az a vevő, ha kimutatást kell rá készíteni akkor ez nem jó
- összetett kulcsot használsz

vevo(id, id_mod, nev, adoszam)

és akkor a

szamla_fej(id, id_vevo, id_vevo_mod)

táblában is ez alapján van a kapcsolat így a helyes adatokat fogja mindig mutatni és ha kell valami kimutatás a vevőre akkor ugye az id-je az ugyan az marad így könnyű lekérni.

Na ennek a kezeléséhez lenne jó valami támogatás a JAP részéről.
Van pl. a project entitás, van 60 mezője, ebből 40 nyugodtan megváltoztatható nem oszt nem szoroz, nyugodtan mehet egy update, ellenben van 20 kritikus mező, mely amelyből ha legalább egy megváltozik akkor már egy insertnek kellene mennie úgy, hogy a az id marad az eredeti és az id_mod növekszik egyel.

Azt kiszámoltad, hogy ha ezeket a plusz mezőket hozzáraknád a szamla_fej táblához, akkor a hízás az a valóságos terhelés mellett mit jelentene? Mert simán lehet, hogy csak néhány száz megbájt plusz lenne, viszont az üzleti logikát nagyon komolyan egyszerűsödne.

Egyébként amit most leírtál, az kb. üzleti logika, tehát azt a BL osztályodba kellene szerintem rakni, és nem az adatbázis modellbe. Ha ilyet akarsz, én erre csinálnék egy dao pattern-t, és azon keresztül oldanám ezt meg. Sőt, igazából teljesen különválasztanám az üzleti logikában lévő entitások és ezek tárolását egymástól, és egy repository-t használnék, lásd Clean Architecture.

Az Envers-et azért nézd meg, mert szerintem az pont megoldja azt, amit szeretnél. Az úgy működik, hogy egy táblához csinál egy segédtáblát, a táblád az utolsó módosítás értékét tárolja, a segédtáblában viszont minden módosítást nyomon lehet követni, és ad API-t arra, hogy ha kiváncsi vagy arra, hogy X időben mi volt az érték, azt meg tudja neked mondani, vagy hogy milyen változások voltak, azt is. Ezt egyébként egy triggerrel is meg tudod csinálni.

EclipseLink-hez van egyébként valami hasonló, http://wiki.eclipse.org/EclipseLink/Examples/JPA/History

https://bytefish.de/blog/hibernate_envers_versioning_and_auditing/

+1

Az lehet, hogy a mezők tárolása a fejhez nem éppen a legszebb, de a tárhelyköltséget valóságos terhelés mellett is messze meghaladja az az overkill, ami egy egyszerű éves kimutatás esetén fennáll. És az többször fut, sokszor oktalanul is (pl egy webshop dashboardja, amin az elmúlt időszak is fenn van).
A fejlesztési költség növekedéséről meg ne is beszéljünk, a jó isten se fogja átlátni, amikor egy riportot akar csinálni.