@ManyToMany

Elérhető

Szervizasztal

Most nézzünk egy másik gyakori esetet – sok-sok. Képzeljük el, hogy sok-sok kapcsolat van a feladatok és az alkalmazottak között :

  • Az alkalmazotti táblában egy alkalmazott sok feladatot elvégezhet a feladattáblából.
  • A feladattáblázatban egy feladat több alkalmazotthoz is hozzárendelhető.

Ezt az entitások közötti kapcsolatot sok-sok-hoz hívják. És ahhoz, hogy SQL szinten megvalósítsuk, szükségünk van egy további szolgáltatási táblára. Nevezzük például alkalmazott_feladatnak.

A munkavállaló_feladat tábla csak két oszlopot tartalmaz:

  • munkavállalói azonosító
  • feladat_azonosítója

Minden alkalommal, amikor egy adott feladatot rendelünk egy adott felhasználóhoz, egy új sor kerül hozzáadásra ehhez a táblázathoz. Példa:

munkavállalói azonosító feladat_azonosítója
1 1
1 2
2 3

Nos, a feladattáblának el kell veszítenie az alkalmazott_azonosító oszlopát . Ennek csak akkor van értelme, ha a feladatot csak egy alkalmazotthoz lehet hozzárendelni. Ha a feladat több alkalmazotthoz is hozzárendelhető, akkor ezeket az információkat a munkavállaló_feladat szolgáltatástáblában kell tárolni .

Táblázat szintű kapcsolat

Így fognak kinézni új asztalaink:

id név Foglalkozása fizetés kor csatlakozás dátuma
1 Ivanov Iván Programozó 100 000 25 2012-06-30
2 Petrov Petr Programozó 80000 23 2013-08-12
3 Ivanov Szergej Vizsgáló 40000 harminc 2014-01-01
4 Rabinovics Moisa Rendező 200 000 35 2015-05-12
5 Kirienko Anasztázia Irodavezető 40000 25 2015-10-10
6 Vaska Macska 1000 3 2018-11-11

Alkalmazottak táblázata ( nem változott ) :

Ez a táblázat a következő oszlopokat tartalmazza:

  • azonosító INT
  • név VARCHAR
  • foglalkozás VARCHAR
  • fizetés INT
  • kor INT
  • csatlakozási_dátum DATE

És így néz ki a feladattábla , elvesztette a munkavállaló_id oszlopát (pirossal jelölve):

id employee_id név határidő
1 1 Javítson ki egy hibát a kezelőfelületen 2022-06-01
2 2 Javítson ki egy hibát a háttérben 2022-06-15
3 5 Vegyél kávét 2022-07-01
4 5 Vegyél kávét 2022-08-01
5 5 Vegyél kávét 2022-09-01
6 (NULLA) Takarítsd ki az irodát (NULLA)
7 4 Élvezd az életet (NULLA)
8 6 Élvezd az életet (NULLA)

Ez a táblázat már csak 3 oszlopot tartalmaz:

  • id - egyedi feladatszám (és sorok a táblázatban)
  • munkavállalói_azonosító – (eltávolítva)
  • név - a feladat neve és leírása
  • határidő - az az idő, ameddig a feladatot el kell végezni

Rendelkezünk a munkavállalói_feladat szolgáltatási táblával is , ahol a munkavállalói_id adatok áttelepültek a feladattáblából:

munkavállalói azonosító feladat_azonosítója
1 1
2 2
5 3
5 4
5 5
(NULLA) 6
4 7
6 8

Szándékosan mentettem el ideiglenesen a törölt oszlopot a feladattáblába, így láthatja, hogy az abból származó adatok átkerültek az alkalmazott_feladat táblába.

Egy másik fontos pont a "(NULL) 6" piros vonal a munkavállaló_feladat táblában. Pirossal jelöltem, mert nem lesz benne az alkalmazott_feladat táblában .

Ha a 7. feladat a 4. felhasználóhoz van hozzárendelve, akkor a munkavállaló_feladat táblában legyen egy sor (4, 7).

Ha a 6. feladat nincs hozzárendelve senkihez, akkor egyszerűen nem lesz róla rekord a munkavállaló_feladat táblában. Így fognak kinézni a táblázatok végleges verziói:

feladat táblázat :

id név határidő
1 Javítson ki egy hibát a kezelőfelületen 2022-06-01
2 Javítson ki egy hibát a háttérben 2022-06-15
3 Vegyél kávét 2022-07-01
4 Vegyél kávét 2022-08-01
5 Vegyél kávét 2022-09-01
6 Takarítsd ki az irodát (NULLA)
7 Élvezd az életet (NULLA)
8 Élvezd az életet (NULLA)

munkavállaló_feladat táblázat:

munkavállalói azonosító feladat_azonosítója
1 1
2 2
5 3
5 4
5 5
4 7
6 8

Kommunikáció Java osztályszinten

De az Entity-osztályok szintű kommunikációval teljes a rendünk. Kezdjük a jó hírrel.

Először is, a Hibernate egy speciális @ManyToMany megjegyzéssel rendelkezik , amely lehetővé teszi a sok a sokhoz tábla kapcsolat esetének megfelelő leírását.

Másodszor, két Entity osztály még mindig elég nekünk. A szervizasztalhoz nincs szükségünk osztályra.

Így fognak kinézni az óráink. Az Employee osztály eredeti formájában:

@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @Column(name="occupation")
   public String occupation;

   @Column(name="salary")
   public Integer salary;

   @Column(name="join_date")
   public Date join;
}

És az EmployeeTask osztály eredeti formájában:

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String description;

   @Column(name="deadline")
   public Date deadline;
}

@ManyToMany kommentár

A példákban a meglévő mezőket kihagyom, de újakat adok hozzá. Így fognak kinézni. Alkalmazotti osztály :

@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
	       joinColumns=  @JoinColumn(name="employee_id", referencedColumnName="id"),
           inverseJoinColumns= @JoinColumn(name="task_id", referencedColumnName="id") )
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();

}

És az EmployeeTask osztály :

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
       	joinColumns=  @JoinColumn(name="task_id", referencedColumnName="id"),
       	inverseJoinColumns= @JoinColumn(name=" employee_id", referencedColumnName="id") )
   private Set<Employee> employees = new HashSet<Employee>();

}

Úgy tűnik, hogy minden bonyolult, de valójában minden egyszerű.

Először is a @JoinTable annotációt használja (nem tévesztendő össze a @JoinColumn-nel), amely leírja a munkavállalói_feladat szolgáltatási táblát.

Másodszor, leírja, hogy a munkavállaló_feladat tábla task_id oszlopa a feladattábla id oszlopára hivatkozik.

Harmadszor azt mondja, hogy a munkavállaló_feladat tábla munkavállalói_azonosító oszlopa az alkalmazotti tábla id oszlopára vonatkozik.

Tulajdonképpen annotációk segítségével leírtuk, hogy a munkavállaló_feladat tábla milyen adatokat tartalmaz, és a Hibernate hogyan értelmezze azokat.

De most nagyon könnyen hozzáadhatunk (és törölhetünk) egy feladatot bármelyik alkalmazotthoz. És bármilyen előadót hozzáadhat bármilyen feladathoz.

Kérjen példákat

Írjunk néhány érdekes kérdést, hogy jobban megértsük, hogyan működnek ezek a ManyToMany mezők. És pontosan az elvárásoknak megfelelően működnek.

Először is, a régi kódunk változtatás nélkül fog működni, mivel a rendezőnek korábban volt feladatmezője:

EmployeeTask task1 = new EmployeeTask();
task1.description = "Do Something Important";
session.persist(task1);

EmployeeTask task2 = new EmployeeTask();
task2.description = "Nothing to do";
session.persist(task2);
session.flush();

Employee director = session.find(Employee.class, 4);
director.tasks.add(task1);
director.tasks.add(task2);

session.update(director);
session.flush();

Másodszor, ha egy feladathoz egy másik előadót akarunk hozzárendelni, akkor ezt még egyszerűbb megtenni:

Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);

session.update(task);
session.flush();

Fontos! Ezen felkérés teljesítése következtében nemcsak a feladatnak lesz végrehajtó-irányítója, hanem az igazgatónak is lesz 101. számú feladata.

Először is, az igazgató és a feladat közötti kapcsolat ténye az alkalmazott_feladat táblában karakterláncként kerül tárolásra: (4,101).

Másodszor, a @ManyToMany megjegyzésekkel jelölt mezők proxy objektumok, és amikor elérjük őket, akkor mindig adatbázis-lekérdezés kerül végrehajtásra.

Tehát ha felvesz egy feladatot egy alkalmazotthoz és elmenti az adatbázisba az alkalmazott adatait, akkor ezután a feladatnak új végrehajtója lesz a végrehajtók listájában.

Hozzászólások
  • Népszerű
  • Új
  • Régi
Hozzászólás írásához be kell jelentkeznie
Ennek az oldalnak még nincsenek megjegyzései