@Veel te veel

Beschikbaar

Service tafel

Laten we nu eens kijken naar een ander veelvoorkomend geval: veel-op-veel. Laten we ons voorstellen dat we een veel-op-veel- relatie hebben tussen taken en werknemers :

  • Eén medewerker in de medewerkerstabel kan veel taken uitvoeren vanuit de takentabel.
  • Eén taak in de takentabel kan aan meerdere medewerkers worden toegewezen.

Deze relatie tussen entiteiten wordt veel-op-veel genoemd. En om het op SQL-niveau te implementeren, hebben we een extra servicetabel nodig. Laten we het bijvoorbeeld werknemer_taak noemen.

De tabel employee_task bevat slechts twee kolommen:

  • medewerker_id
  • taak_id

Elke keer dat we een specifieke taak aan een specifieke gebruiker toewijzen, wordt er een nieuwe rij aan deze tabel toegevoegd. Voorbeeld:

medewerker_id taak_id
1 1
1 2
2 3

Welnu, de taaktabel zou zijn kolom employee_id moeten verliezen . Het heeft alleen zin als de taak maar aan één medewerker kan worden toegewezen. Als de taak aan meerdere medewerkers kan worden toegewezen, moet deze informatie worden opgeslagen in de servicetabel employee_task .

Relatie op tafelniveau

Zo zien onze nieuwe tafels eruit:

ID kaart naam bezigheid salaris leeftijd join_date
1 Ivanov Ivan Programmeur 100000 25 2012-06-30
2 Petrov Petr Programmeur 80000 23 2013-08-12
3 Ivanov Sergej Tester 40000 dertig 01-01-2014
4 Rabinovich Moisha Regisseur 200000 35 2015-05-12
5 Kirienko Anastasia Officemanager 40000 25 2015-10-10
6 Vaska Kat 1000 3 2018-11-11

Werknemerstabel ( niet gewijzigd ) :

Deze tabel heeft de volgende kolommen:

  • id INT
  • naam VARCHAR
  • bezetting VARCHAR
  • salaris INT
  • leeftijd INT
  • join_date DATUM

En zo ziet de taaktabel eruit , de kolom employee_id verloren (rood gemarkeerd):

ID kaart medewerker_id naam deadline
1 1 Los een bug op de frontend op 01-06-2022
2 2 Los een bug op de backend op 2022-06-15
3 5 Koop koffie 01-07-2022
4 5 Koop koffie 01-08-2022
5 5 Koop koffie 01-09-2022
6 (NUL) Ruim het kantoor op (NUL)
7 4 Geniet van het leven (NUL)
8 6 Geniet van het leven (NUL)

Deze tabel heeft nu slechts 3 kolommen:

  • id - uniek taaknummer (en rijen in de tabel)
  • werknemer_id - (verwijderd)
  • naam - de naam en beschrijving van de taak
  • deadline - de tijd tot wanneer de taak moet worden voltooid

We hebben ook de employee_task-servicetabel , waar de employee_id-gegevens zijn gemigreerd vanuit de taaktabel:

medewerker_id taak_id
1 1
2 2
5 3
5 4
5 5
(NUL) 6
4 7
6 8

Ik heb met opzet de verwijderde kolom tijdelijk in de taaktabel opgeslagen, zodat u kunt zien dat de gegevens ervan zijn verplaatst naar de tabel employee_task.

Een ander belangrijk punt is de rode lijn "(NULL) 6" in de tabel employee_task. Ik heb het rood gemarkeerd omdat het niet in de tabel employee_task staat .

Als taak 7 is toegewezen aan gebruiker 4, moet er een rij (4, 7) zijn in de tabel employee_task.

Als taak 6 aan niemand is toegewezen, is er simpelweg geen record voor in de tabel employee_task. Dit is hoe de definitieve versies van deze tabellen eruit zullen zien:

taak tabel :

ID kaart naam deadline
1 Los een bug op de frontend op 01-06-2022
2 Los een bug op de backend op 2022-06-15
3 Koop koffie 01-07-2022
4 Koop koffie 01-08-2022
5 Koop koffie 01-09-2022
6 Ruim het kantoor op (NUL)
7 Geniet van het leven (NUL)
8 Geniet van het leven (NUL)

tabel werknemer_taak:

medewerker_id taak_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8

Communicatie op het niveau van de Java-klasse

Maar met communicatie op het niveau van Entity-klassen hebben we een complete bestelling. Laten we beginnen met het goede nieuws.

Ten eerste heeft Hibernate een speciale @ManyToMany- annotatie waarmee u het geval van een veel-op-veel-tabelrelatie goed kunt beschrijven.

Ten tweede zijn twee Entity-klassen nog steeds genoeg voor ons. We hebben geen klasse nodig voor de servicetafel.

Zo zien onze lessen eruit. De klasse Employee in zijn oorspronkelijke vorm:

@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;
}

En de klasse EmployeeTask in zijn oorspronkelijke vorm:

@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-annotatie

Ik zal de bestaande velden in de voorbeelden weglaten, maar ik zal nieuwe toevoegen. Hier is hoe ze eruit zullen zien. Werknemer klasse :

@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>();

}

En de EmployeeTask -klasse :

@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>();

}

Het lijkt erop dat alles ingewikkeld is, maar in feite is alles eenvoudig.

Ten eerste gebruikt het de annotatie @JoinTable (niet te verwarren met @JoinColumn), die de servicetabel employee_task beschrijft.

Ten tweede beschrijft het dat de kolom task_id van de tabel employee_task verwijst naar de kolom id van de taaktabel.

Ten derde staat er dat de kolom employee_id van de tabel employee_task verwijst naar de kolom id van de werknemerstabel.

Met behulp van annotaties hebben we zelfs beschreven welke gegevens in de tabel employee_task staan ​​en hoe Hibernate deze moet interpreteren.

Maar nu kunnen we heel eenvoudig een taak toevoegen (en verwijderen) aan elke medewerker. En voeg ook elke artiest toe aan elke taak.

Vraag voorbeelden aan

Laten we een paar interessante vragen schrijven om beter te begrijpen hoe deze ManyToMany-velden werken. En ze werken precies zoals verwacht.

Ten eerste zal onze oude code zonder wijzigingen werken, aangezien de directeur eerder een takenveld had:

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();

Ten tweede, als we een andere artiest aan een bepaalde taak willen toewijzen, dan is het nog eenvoudiger om dit te doen:

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

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

Belangrijk! Door uitvoering van dit verzoek krijgt niet alleen de taak een uitvoerder-directeur, maar krijgt ook de directeur taak nr. 101.

Eerst wordt het feit over de relatie tussen de directeur en de taak in de tabel employee_task opgeslagen als een string: (4,101).

Ten tweede zijn de velden gemarkeerd met @ManyToMany- annotaties proxy-objecten en wanneer ze worden geopend, wordt er altijd een databasequery uitgevoerd.

Dus als je een taak toevoegt aan een medewerker en informatie over de medewerker opslaat in de database, dan krijgt de taak daarna een nieuwe uitvoerder in de lijst met uitvoerders.

Opmerkingen
  • Populair
  • Nieuw
  • Oud
Je moet ingelogd zijn om opmerkingen te kunnen maken
Deze pagina heeft nog geen opmerkingen