Mapovanie jedného subjektu do viacerých tabuliek v JPA

Perzistencia hore

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

1. Úvod

JPA robí prácu s relačnými databázovými modelmi z našich Java aplikácií menej bolestivou. Veci sú jednoduché, keď mapujeme každú tabuľku do jednej triedy entít. Niekedy však máme dôvody modelovať naše entity a tabuľky inak:

  • Ak chceme vytvoriť logické skupiny polí, môžeme namapovať viac tried na jednu tabuľku
  • Ak je to spojené s dedičstvom, môžeme mapovať hierarchiu tried na štruktúru tabuľky
  • V prípadoch, keď sú súvisiace polia rozptýlené medzi viac tabuliek, a chceme tieto tabuľky modelovať pomocou jednej triedy

V tomto krátkom návode uvidíme, ako vyriešiť tento posledný scenár.

2. Dátový model

Povedzme, že prevádzkujeme reštauráciu a chceme ukladať údaje o každom jedle, ktoré podávame:

  • názov
  • popis
  • cena
  • aký druh alergénov obsahuje

Pretože existuje veľa možných alergénov, zoskupíme tento súbor údajov. Ďalej to tiež vymodelujeme pomocou nasledujúcich definícií tabuľky:

Teraz sa pozrime, ako môžeme tieto tabuľky mapovať na entity pomocou štandardných anotácií JPA.

3. Vytvorenie viacerých entít

Najzrejmejším riešením je vytvorenie entity pre obe triedy.

Začnime definovaním Jedlo subjekt:

@Entity @Table (name = "meal") trieda jedlo {@Id @GeneratedValue (strategy = GenerationType.IDENTITY) @Column (name = "id") Long id; @Column (name = "name") Názov reťazca; @Column (name = "description") Popis reťazca; @Column (name = "price") BigDecimal price; @OneToOne (mappedBy = "jedlo") Alergénne alergény; // štandardné getre a setre}

Ďalej pridáme Alergény subjekt:

@Entity @Table (name = "alergény") trieda Alergény {@Id @GeneratedValue (strategy = GenerationType.IDENTITY) @Column (name = "meal_id") Dlhé jedloId; @OneToOne @PrimaryKeyJoinColumn (name = "meal_id") Stravovacie jedlo; @Column (name = "arašidy") boolean arašidy; @Column (name = "celer") boolean zeler; @Column (name = "sesame_seeds") boolean sesameSeeds; // štandardné getre a setre}

Na uvedenom príklade to vidíme jedlo_id je primárny kľúč aj cudzí kľúč. To znamená, že musíme definovať stĺpec vzťahu jedna k jednej pomocou @PrimaryKeyJoinColumn.

Toto riešenie má však dva problémy:

  • Vždy chceme mať pri jedle uskladnené alergény a toto riešenie toto pravidlo nepresadzuje
  • Údaje o jedle a alergénoch patria logicky - preto by sme mohli chcieť tieto informácie uložiť do rovnakej triedy Java, aj keď sme pre ne vytvorili viac tabuliek

Jedným z možných riešení prvého problému je pridanie súboru @NotNull anotácia k alergény pole na našom Jedlo subjekt. JPA nám nedovolí pokračovať Jedlo ak máme nulovýAlergény.

Nie je to však ideálne riešenie; chceme viac obmedzujúci, kde nemáme ani možnosť pokúsiť sa vytrvať a Jedlo bez Alergény.

4. Vytvorenie jediného subjektu pomocou @SecondaryTable

Môžeme vytvoriť jednu entitu špecifikujúcu, že máme stĺpce v rôznych tabuľkách pomocou @SecondaryTable anotácia:

@Entity @Table (name = "jedlo") @SecondaryTable (name = "alergény", pkJoinColumns = @PrimaryKeyJoinColumn (name = "meal_id")) jedlo triedy {@Id @GeneratedValue (strategy = GenerationType.IDENTITY) @Column (názov = "id") Long id; @Column (name = "name") Názov reťazca; @Column (name = "description") Popis reťazca; @Column (name = "price") BigDecimal price; @Column (name = "arašidy", tabuľka = "alergény") boolean arašidy; @Column (name = "zeler", table = "alergény") zeler zeler; @Column (name = "sesame_seeds", table = "alergény") boolean sesameSeeds; // štandardné getre a setre}

V zákulisí sa JPA spojí s primárnou tabuľkou so sekundárnou tabuľkou a vyplní polia. Toto riešenie je podobné ako @Jeden na jedného vzťah, ale takto môžeme mať všetky vlastnosti v rovnakej triede.

Je dôležité si to uvedomiťak máme stĺpec, ktorý je v sekundárnej tabuľke, musíme ho určiť pomocou stôl argument @ Stĺpec anotácia. Ak je stĺpec v primárnej tabuľke, môžeme vynechať stôl argument, pretože JPA štandardne vyhľadáva stĺpce v primárnej tabuľke.

Upozorňujeme tiež, že môžeme mať viac sekundárnych tabuliek, ak ich vložíme @SecondaryTables. Prípadne z Java 8 môžeme entitu označiť viacerými @SecondaryTable anotácie, pretože ide o opakovateľnú anotáciu.

5. Kombinovanie @SecondaryTable S @ Zabudované

Ako sme videli, @SecondaryTable mapuje viac tabuliek na rovnakú entitu. To tiež vieme @ Zabudované a @Vložiteľné urobiť opak a namapovať jednu tabuľku na viac tried.

Pozrime sa, čo dostaneme, keď skombinujeme @SecondaryTable s @ Zabudované a @Embeddable:

@Entity @Table (name = "jedlo") @SecondaryTable (name = "alergény", pkJoinColumns = @PrimaryKeyJoinColumn (name = "meal_id")) jedlo triedy {@Id @GeneratedValue (strategy = GenerationType.IDENTITY) @Column (názov = "id") Long id; @Column (name = "name") Názov reťazca; @Column (name = "description") Popis reťazca; @Column (name = "price") BigDecimal price; @ Zabudované alergény alergénov; // štandardní vyhľadávači a nastavovatelia} @Embeddable trieda Alergény {@Column (name = "arašidy", tabuľka = "alergény") boolean arašidy; @Column (name = "zeler", table = "alergény") zeler boolean; @Column (name = "sesame_seeds", table = "alergény") boolean sesameSeeds; // štandardné getre a setre}

Je to podobný prístup k tomu, čo sme videli používať @Jeden na jedného. Má to však niekoľko výhod:

  • Spoločné parlamentné zhromaždenie za nás tieto dva stoly spravuje spoločne, takže si môžeme byť istí, že v oboch stoloch bude riadok pre každé jedlo
  • Kód je tiež o niečo jednoduchší, pretože potrebujeme menšiu konfiguráciu

Toto individuálne riešenie však funguje, iba ak majú dve tabuľky zodpovedajúce ID.

Za zmienku stojí, že ak chceme znovu použiť Alergény triedy, bolo by lepšie, keby sme definovali stĺpce sekundárnej tabuľky v Jedlo trieda s @AttributeOverride.

6. Záver

V tomto krátkom tutoriáli sme videli, ako môžeme pomocou @SecondaryTable Anotácia JPA.

Videli sme aj výhody kombinovania @SecondaryTable s @ Zabudované a @Embeddable získať vzťah podobný dvojici.

Ako obvykle sú príklady k dispozícii na GitHub.

Perzistencia dno

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ

$config[zx-auto] not found$config[zx-overlay] not found