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.ALL
betyr at alle handlinger vi utfører med det overordnede objektet må gjentas for dets avhengige objekter.
CascadeType.PERSIST
betyr 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.MERGE
betyr 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.REMOVE
betyr at hvis vi sletter et overordnet objekt i databasen, så må det samme gjøres med dets avhengige objekter.
CascadeType.DELETE
betyr det samme. Dette er synonymer. Bare fra forskjellige spesifikasjoner.
CascadeType.DETACH
betyr 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.REFRESH
og CascadeType.SAVE_UPDATE
fungerer 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.
GO TO FULL VERSION