Sok-sok kapcsolat a JPA-ban

1. Bemutatkozás

Ebben az oktatóanyagban többféle módot fogunk megtudni foglalkozzon sok-sok kapcsolattal a JPA segítségével.

Az ötletek bemutatásához a hallgatók, tanfolyamok és a közöttük lévő különféle kapcsolatok modelljét használjuk.

Az egyszerűség kedvéért a kódpéldákban csak azokat az attribútumokat és JPA konfigurációt mutatjuk be, amelyek a sok-sok kapcsolathoz kapcsolódnak.

2. Alapvető sok-sok

2.1. Sok-sok kapcsolat modellezése

A kapcsolat két típusú entitás közötti kapcsolat. Sok-sok kapcsolat esetén mindkét fél a másik fél több példányához kapcsolódhat.

Ne feledje, hogy az entitástípusok kapcsolatban lehetnek önmagukkal. Például, amikor családfákat modellezünk: minden csomópont egy személy, tehát ha a szülő-gyermek kapcsolatról beszélünk, mindkét résztvevő személy lesz.

Azonban nincs ilyen különbség, hogy egyetlen vagy több entitástípus közötti kapcsolatról beszélünk. Mivel könnyebb két különböző entitástípus közötti kapcsolatokra gondolni, ezt felhasználjuk eseteink illusztrálására.

Például, amikor a hallgatók megjelölik a nekik tetsző tanfolyamokat: egy diák kedvelheti sok tanfolyamok, és sok a hallgatók kedvelhetik ugyanezt a tanfolyamot:

Mint tudjuk, az RDBMS-ekben kapcsolatokat hozhatunk létre idegen kulcsokkal. Mivel mindkét félnek képesnek kell lennie a másikra való hivatkozásra, külön táblázatot kell létrehoznunk az idegen kulcsok tárolására:

Az ilyen táblázatot a csatlakozzon asztalhoz. Ne feledje, hogy egy csatlakozási táblában az idegen kulcsok kombinációja lesz az összetett elsődleges kulcs.

2.2. Végrehajtás a JPA-ban

Sok-sok kapcsolat modellezése POJO-kkal könnyű. Nekünk kellene tartalmazza a Gyűjtemény mindkét osztályban, amely tartalmazza a többiek elemeit.

Ezt követően meg kell jelölnünk az osztályt @Entity, és az elsődleges kulcsot a gombbal @Id hogy azok megfelelő JPA-entitásokká váljanak.

Be kell állítanunk a kapcsolattípust is. Ennélfogva a gyűjteményeket azzal jelöljük @ManyToMany kommentárok:

@Entity osztály Tanuló {@Id Long id; @ManyToMany Set likesCourses; // további tulajdonságok // szabványos kivitelezők, mérőeszközök és beállítók} @Entity class Course {@Id Long id; @ManyToMany Set tetszik; // további tulajdonságok // szabványos kivitelezők, mérőeszközök és beállítók}

Ezenkívül konfigurálnunk kell a kapcsolat modellezését az RDBMS-ben.

A tulajdonos oldalon konfiguráljuk a kapcsolatot, amelyet ehhez a példához választunk Diák osztály.

Megtehetjük ezt a @JoinTable annotáció a Diák osztály. Megadjuk a csatlakozási táblázat nevét (tanfolyam_szerű), és az idegen kulcsokat a @JoinColumn annotációk. A joinColumn attribútum a kapcsolat tulajdonosi oldalához fog kapcsolódni, és a inverseJoinColumn a másik oldalra:

@ManyToMany @JoinTable (name = "course_like", joinColumns = @JoinColumn (name = "student_id"), inverseJoinColumns = @JoinColumn (name = "course_id")) Set likedCourses;

Ne feledje, hogy a @JoinTable, vagy akár @JoinColumn nem szükséges: a JPA generálja számunkra a táblázat és oszlop nevét. A JPA által alkalmazott stratégia azonban nem mindig egyezik meg az általunk használt elnevezési szokásokkal. Ezért lehetőség van a táblák és oszlopok nevének konfigurálására.

A céloldalon csak a mező nevét kell megadnunk, amely feltérképezi a kapcsolatot. Ezért beállítottuk a feltérképezve attribútuma @ManyToMany annotáció a Tanfolyam osztály:

@ManyToMany (mappedBy = "likedCourses") Állítsa be a like-okat;

Ne feledje, hogy mivel a sok-sok kapcsolatnak nincs tulajdonosi oldala az adatbázisban, konfigurálhatjuk a csatlakozási táblázatot a Tanfolyam osztály és hivatkozás a Diák osztály.

3. Sok-sok a kompozit kulcs használata

3.1. A kapcsolattulajdonságok modellezése

Tegyük fel, hogy szeretnénk hagyni, hogy a hallgatók értékeljék a tanfolyamokat. Egy hallgató tetszőleges számú tanfolyamot értékelhet, és tetszőleges számú tanuló értékelheti ugyanazt a tanfolyamot. Ezért sok-sok kapcsolat is. Ami egy kicsit bonyolultabbá teszi, az az több van a minősítési viszonyban, mint az, hogy létezik. Tárolnunk kell a tanuló által a tanfolyamon adott minősítési pontszámot.

Hol tárolhatjuk ezeket az információkat? Nem tehetjük bele Diák mivel egy hallgató különböző minősítéseket adhat a különböző tanfolyamoknak. Hasonlóképpen tárolja a Tanfolyam entitás sem lenne jó megoldás.

Ez egy olyan helyzet, amikor magának a kapcsolatnak van attribútuma.

E példa segítségével egy attribútum hozzárendelése egy relációhoz így néz ki egy ER diagramban:

Szinte ugyanúgy modellezhetjük, mint az egyszerű sok-sok kapcsolat esetén. Az egyetlen különbség az, hogy új attribútumot csatolunk a csatlakozási táblához:

3.2. Kompozit kulcs létrehozása a JPA-ban

Az egyszerű sok-sok kapcsolat megvalósítása meglehetősen egyszerű volt. Az egyetlen probléma az, hogy nem adhatunk hozzá tulajdonságot egy kapcsolathoz így, mert közvetlenül csatlakoztattuk az entitásokat. Ebből kifolyólag, nem volt módunk hozzáadni egy tulajdonságot magához a kapcsolathoz.

Mivel a DB attribútumokat leképezzük a JPA osztályterületeire, létre kell hoznunk egy új entitásosztályt a kapcsolathoz.

Természetesen minden JPA-entitásnak szüksége van egy elsődleges kulcsra. Mivel az elsődleges kulcsunk egy összetett kulcs, létre kell hoznunk egy új osztályt, amely megtartja a kulcs különböző részeit:

@Embeddable class A CourseRatingKey a Serializable {@Column (name = "student_id") hosszú studentId; @Column (név = "tanfolyam_azonosító") Long courseId; // szabványos konstruktorok, mérőeszközök és beállítók // hashcode és egyenlő a megvalósítással}

Ne feledje, hogy vannak ilyenek kulcsfontosságú követelmények, amelyeknek az összetett kulcsosztálynak meg kell felelnie:

  • Meg kell jelölnünk @ Beágyazható
  • Meg kell valósítani java.io.Serializálható
  • Biztosítanunk kell a hash kód() és egyenlő () mód
  • Egyik mező sem lehet entitás

3.3. Kompozit kulcs használata a JPA-ban

Ezen összetett kulcsosztály használatával létrehozhatjuk az entitás osztályt, amely modellezi a csatlakozási táblázatot:

@Entity osztály CourseRating {@EmbeddedId CourseRatingKey id; @ManyToOne @MapsId ("studentId") @JoinColumn (név = "student_id") Diákhallgató; @ManyToOne @MapsId ("courseId") @JoinColumn (name = "course_id") Tanfolyam tanfolyam; int minősítés; // szabványos kivitelezők, mérőeszközök és beállítók}

Ez a kód nagyon hasonlít a szokásos entitásmegvalósításhoz. Van néhány kulcsfontosságú különbségünk:

  • használtuk @EmbeddedId, az elsődleges kulcs megjelöléséhez, amely a CourseRatingKey osztály
  • megjelöltük a diák és tanfolyam mezők @MapsId

@MapsId azt jelenti, hogy ezeket a mezőket a kulcs egy részéhez kötjük, és ezek a sok az egyhez viszony idegen kulcsai. Szükségünk van rá, mert ahogy fentebb említettük, az összetett kulcsban nem lehetnek entitásaink.

Ezek után konfigurálhatjuk az inverz referenciákat a Diák és Tanfolyam olyan szervezetek, mint korábban:

osztály Tanuló {// ... @OneToMany (mappedBy = "hallgató") Értékelés beállítása; // ...} osztály Tanfolyam {// ... @OneToMany (mappedBy = "course") Értékelés beállítása; // ...}

Ne feledje, hogy van egy alternatív mód az összetett kulcsok használatára: a @IdClass annotáció.

3.4. További jellemzők

Konfiguráltuk a kapcsolatokat a Diák és Tanfolyam osztályok as @ManyToOne. Megtehettük, mert az új entitással strukturálisan megbontottuk a sok a sokhoz viszonyát a két sok az egyhez viszonyhoz.

Miért voltunk képesek erre? Ha az előző esetben alaposan megvizsgáljuk a táblázatokat, láthatjuk, hogy két sok-egy kapcsolat volt. Más szavakkal, az RDBMS-ben nincs sok a sokhoz viszony. Az egyesített táblákkal létrehozott struktúrákat sok-sok kapcsolatnak hívjuk, mert ezt modellezzük.

Emellett egyértelműbb, ha sok-sok kapcsolatról beszélünk, mert ez a szándékunk. Eközben a csatlakozási asztal csak egy megvalósítási részlet; nem igazán érdekel.

Sőt, ennek a megoldásnak van egy további funkciója, amelyet még nem említettünk. Az egyszerű sok-sok megoldás kapcsolatot hoz létre két entitás között. Ezért nem bővíthetjük a kapcsolatot több entitásra. Ebben a megoldásban azonban nincs ez a korlát: tetszőleges számú entitástípus között modellezhetjük a kapcsolatokat.

Például amikor több tanár is taníthat egy tanfolyamot, a hallgatók értékelhetik, hogy egy adott tanár hogyan tanít egy adott tanfolyamot. Így a minősítés három entitás kapcsolata lenne: egy hallgató, egy tanfolyam és egy tanár.

4. Sok-sok-sok új entitással

4.1. A kapcsolattulajdonságok modellezése

Tegyük fel, hogy meg akarjuk engedni a hallgatóknak, hogy regisztráljanak a tanfolyamokra. Is, tárolnunk kell azt a pontot, amikor egy hallgató regisztrált egy adott tanfolyamra. Ráadásul azt is szeretnénk tárolni, hogy milyen osztályzatot kapott a tanfolyamon.

Egy ideális világban ezt megoldhatnánk az előző megoldással, amikor volt egy összetett kulccsal rendelkező entitás. Világunk azonban korántsem ideális, és a hallgatók nem mindig végeznek tanfolyamot első próbálkozással.

Ebben az esetben vannak több kapcsolat ugyanazon hallgató-tanfolyam párok között, vagy több sor, ugyanazzal student_id-tanfolyam_id párok. Az előző megoldások egyikével sem modellezhetjük, mert minden elsődleges kulcsnak egyedinek kell lennie. Ezért külön elsődleges kulcsot kell használnunk.

Ebből kifolyólag, bemutathatunk egy entitást, amely a regisztráció attribútumait tartalmazza:

Ebben az esetben, a Regisztráció entitás képviseli a kapcsolatot a másik két entitás között.

Mivel ez egy entitás, saját elsődleges kulccsal rendelkezik.

Megjegyezzük, hogy az előző megoldásnál volt egy összetett elsődleges kulcsunk, amelyet a két idegen kulcsból hoztunk létre. Most a két idegen kulcs nem lesz az elsődleges kulcs része:

4.2. Végrehajtás a JPA-ban

Mivel a coure_registration rendszeres táblává vált, létrehozhatunk egy sima régi JPA entitást, amely ezt modellezi:

@Entity osztály CourseRegistration {@Id Long id; @ManyToOne @JoinColumn (név = "hallgató_id") Diákhallgató; @ManyToOne @JoinColumn (név = "tanfolyam_id") Tanfolyam; LocalDateTime registerAt; int évfolyam; // további tulajdonságok // szabványos kivitelezők, mérőeszközök és beállítók}

Be kell állítanunk a kapcsolatokat a Diák és Tanfolyam osztályok:

osztály Tanuló {// ... @OneToMany (mappedBy = "hallgató") Regisztrációk beállítása; // ...} osztálytanfolyam {// ... @OneToMany (mappedBy = "tanfolyamok") Regisztrációk beállítása; // ...}

Ismét korábban konfiguráltuk a kapcsolatot. Ezért csak meg kell mondanunk a JPA-nak, hol találhatja meg ezt a konfigurációt.

Ne feledje, hogy ezt a megoldást használhatnánk az előző probléma megoldására: a hallgatók tanfolyamok minősítésére. Különös érzés külön dedikált kulcsot létrehozni, hacsak nem muszáj. Ráadásul az RDBMS szempontjából nem sok értelme van, mivel a két idegen kulcs kombinálásával tökéletes összetett kulcs lett. Amellett az összetett kulcsnak egyértelmű jelentése volt: mely entitásokat kapcsoljuk össze a kapcsolatban.

Egyébként a két megvalósítás közötti választás gyakran egyszerűen személyes preferencia.

5. Következtetés

Ebben az oktatóanyagban láttuk, hogy mi a sok-sok kapcsolat, és hogyan modellezhetjük azt egy RDBMS-ben a JPA segítségével.

Három módszert láttunk annak modellezésére a JPA-ban. Mindhárom különböző előnyökkel és hátrányokkal jár:

  • a kód egyértelműsége
  • DB egyértelműsége
  • attribútumok hozzárendelésének képessége a kapcsolathoz
  • hány entitást köthetünk a kapcsolatba, és
  • több entitás közötti kapcsolat támogatása

Szokás szerint a példák elérhetők a GitHub oldalon.