6.1 Dyb afhængighedsstyring
Og nogle flere nyttige og interessante ting om @OneToMany- annoteringer og lignende. De har alle 4 almindeligt anvendte muligheder:
- cascade = CascadeType.ALL
- orphanRemoval = sand
- hente = FetchType.LAZY
Nu vil vi analysere dem mere detaljeret. Og vi starter med den mest interessante - CascadeType . Denne parameter bestemmer, hvad der skal ske med afhængige enheder, hvis vi ændrer hovedenheden.
JPA-specifikationen har følgende værdier for denne parameter:
- ALLE
- VEDHOLDE
- FUSIONERE
- FJERNE
- OPDATER
- LØSRIVE
Dog udvider Hibernate denne specifikation til yderligere tre muligheder:
- GENTAG
- SAVE_UPDATE
- LÅSE
Der er selvfølgelig en stærk parallel til databasen og deres CONSTRANIS. Der er dog også forskelle. Hibernate forsøger at skjule det virkelige arbejde med databasen så meget som muligt, så disse Hibernate Cascades handler præcist om Entity-objekter.
6.2 CascadeType
Kaskadeparameteren beskriver, hvad der skal ske med afhængige objekter, hvis vi ændrer deres forælder (masterobjekt). Oftest bruges denne parameter sammen med anmærkninger, der beskriver objektafhængigheder:
Eksempel:
OneToOne(cascade = CascadeType.ALL)
Eller sådan her:
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
Det kan også skrives som en separat anmærkning:
@Cascade({ org.hibernate.annotations.CascadeType.ALL })
Lad os nu tale mere om, hvad disse annoteringer betyder.
6.3 ALLE, VEDHOLDE, FLETT
CascadeType.ALL
betyder, at alle handlinger , som vi udfører med det overordnede objekt, skal gentages for dets afhængige objekter.
CascadeType.PERSIST
betyder, at hvis vi gemmer det overordnede objekt i databasen, så skal det samme gøres med dets afhængige 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å at arbejde med denne klasse:
Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;
session.persist(director);
session.flush();
Vi gemmer kun et objekt af typen Employee, dets afhængige objekt EmployeeTask gemmes automatisk i databasen.
CascadeType.MERGE
betyder, at hvis vi opdaterer det overordnede objekt i databasen, så skal det samme gøres med dets afhængige objekter.
6.4 FJERN, SLET, AFTAG
CascadeType.REMOVE
betyder, at hvis vi sletter et overordnet objekt i databasen, så skal det samme gøres med dets afhængige objekter.
CascadeType.DELETE
betyder det samme. Det er synonymer. Bare fra forskellige specifikationer.
CascadeType.DETACH
betyder, at hvis vi fjerner det overordnede objekt fra sessionen, så skal det samme gøres med dets afhængige 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å at arbejde med denne klasse:
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åde, som vi forventer - de duplikerer de handlinger, der udføres med det overordnede objekt til dets afhængige objekt.
6.5 Mulighed for fjernelse af forældreløse
Nogle gange kan du også støde på parameteren orphan
. Dette er en forkortelse for Orphan removal. Det bruges til at sikre, at der ikke er nogen underordnede enheder uden overordnede enheder.
OneToOne(orphan = true)
Hvis denne parameter er sat til sand, vil den underordnede enhed blive slettet, hvis den er forsvundetalle links. Det er ikke helt det samme som Cascade.REMOVE
.
Du kan have en situation, hvor flere forældreenheder henviser til ét barn. Så er det fordelagtigt, at det ikke slettes sammen med sletningen af den overordnede enhed, men kun hvis alle referencer til den annulleres.
Lad os sige, 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 blive slettet, fordi der ikke er nogen referencer tilbage til det. Samtidig var der ingen, der slettede det overordnede objekt.
6.6 hente mulighed
Hent-indstillingen giver dig mulighed for at kontrollere, hvordan afhængige objekter indlæses. Det tager normalt en af to værdier:
FetchType.LAZY
FetchType.EAGER
Dette er et meget interessant emne med forskellige faldgruber, så jeg må hellere tale om det i et separat foredrag.
GO TO FULL VERSION