6.1 Dyp avhengighetshåndtering

Og noen flere nyttige og interessante ting om @OneToMany- kommentarer og lignende. De har alle 4 ofte brukte alternativer:

  • cascade = CascadeType.ALL
  • orphanRemoval = sant
  • hente = FetchType.LAZY

Nå vil vi analysere dem mer detaljert. Og vi starter med den mest interessante - CascadeType . Denne parameteren bestemmer hva som skal skje med avhengige enheter hvis vi endrer hovedenheten.

JPA-spesifikasjonen har følgende verdier for denne parameteren:

  • ALLE
  • FORTSETTE
  • SLÅ SAMMEN
  • FJERNE
  • FORFRISKE
  • LØSNE

Hibernate utvider imidlertid denne spesifikasjonen til ytterligere tre alternativer:

  • GJENSKAPE
  • SAVE_UPDATE
  • LÅSE

Det er selvfølgelig en sterk parallell med databasen og deres CONSTRANIS. Det er imidlertid også forskjeller. Hibernate prøver å skjule det virkelige arbeidet med databasen så mye som mulig, så disse Hibernate Cascades handler nøyaktig om Entity-objekter.

6.2 CascadeType

Kaskadeparameteren beskriver hva som skal skje med avhengige objekter hvis vi endrer deres overordnede (masterobjekt). Oftest brukes denne parameteren sammen med merknader som beskriver objektavhengigheter:

Eksempel:

OneToOne(cascade = CascadeType.ALL)

Eller slik:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})

Det kan også skrives som en egen merknad:

@Cascade({ org.hibernate.annotations.CascadeType.ALL })

La oss nå snakke mer om hva disse merknadene betyr.

6.3 ALLE, VEDHOLDE, SLÅ sammen

CascadeType.ALLbetyr at alle handlinger vi utfører med det overordnede objektet må gjentas for dets avhengige objekter.

CascadeType.PERSISTbetyr at hvis vi lagrer det overordnede objektet til databasen, så må det samme gjøres med dets avhengige objekter. Eksempel:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
   private EmployeeTask task;
}

Et eksempel på å jobbe med denne klassen:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
 
session.persist(director);
session.flush();

Vi lagrer kun et objekt av typen Employee, dets avhengige objekt EmployeeTask vil automatisk lagres i databasen.

CascadeType.MERGEbetyr at hvis vi oppdaterer det overordnede objektet i databasen, så må det samme gjøres med dets avhengige objekter.

6.4 FJERN, SLETT, LEVERT

CascadeType.REMOVEbetyr at hvis vi sletter et overordnet objekt i databasen, så må det samme gjøres med dets avhengige objekter.

CascadeType.DELETEbetyr det samme. Dette er synonymer. Bare fra forskjellige spesifikasjoner.

CascadeType.DETACHbetyr at hvis vi fjerner det overordnede objektet fra sesjonen, så må det samme gjøres med dets avhengige objekter. Eksempel:


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
   private EmployeeTask task;
}

Et eksempel på å jobbe med denne klassen:


Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
director.task = task;
session.flush();
 
assertThat(session.contains(director)).isTrue();
assertThat(session.contains(task)).isTrue();
 
session.detach(director);
 
assertThat(session.contains(director)).isFalse();
assertThat(session.contains(task)).isFalse();

CascadeType.REFRESHog CascadeType.SAVE_UPDATEfungerer på samme måte som vi forventer - de dupliserer handlingene som utføres med det overordnede objektet til dets avhengige objekt.

6.5 Alternativ for fjerning av foreldreløse barn

Noen ganger kan du også komme over parameteren orphan. Dette er forkortelse for Orphan removal. Den brukes for å sikre at det ikke er noen underordnede enheter uten overordnede enheter.

OneToOne(orphan = true)

Hvis denne parameteren er satt til sann, vil den underordnede enheten bli slettet hvis den har forsvunnetalle lenker. Det er ikke akkurat det samme som Cascade.REMOVE.

Du kan ha en situasjon der flere overordnede enheter refererer til ett barn. Da er det fordelaktig at den ikke slettes sammen med slettingen av overordnet enhet, men bare hvis alle referanser til den er ugyldig.

La oss si at du har en klasse:


@Entity
@Table(name="user")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL, orphan = true)
   @JoinColumn(name = "employee_id")
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();
}


Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.tasks.get(0);
director.tasks.remove(task)
session.persist(director);
session.flush();

EmployeeTask-objektet vil bli slettet fordi det ikke er noen referanser igjen til det. Samtidig var det ingen som slettet det overordnede objektet.

6.6 hentealternativ

Hent-alternativet lar deg kontrollere hvordan avhengige objekter lastes. Det tar vanligvis en av to verdier:

  • FetchType.LAZY
  • FetchType.EAGER

Dette er et veldig interessant tema med ulike fallgruver, så jeg bør snakke om det i et eget foredrag.