6.1 Djup beroendehantering

Och några mer användbara och intressanta saker om @OneToMany- anteckningar och liknande. De har alla fyra vanliga alternativ:

  • cascade = CascadeType.ALL
  • orphanRemoval = sant
  • hämta = FetchType.LAZY

Nu kommer vi att analysera dem mer i detalj. Och vi börjar med det mest intressanta - CascadeType . Denna parameter bestämmer vad som ska hända med beroende enheter om vi ändrar huvudenheten.

JPA-specifikationen har följande värden för denna parameter:

  • ALLT
  • ENVISAS
  • SAMMANFOGA
  • AVLÄGSNA
  • UPPDATERA
  • LÖSGÖRA

Hibernate utökar dock den här specifikationen till ytterligare tre alternativ:

  • ÅTERSKAPA
  • SAVE_UPDATE
  • LÅSA

Det finns naturligtvis en stark parallell med databasen och deras CONSTRANIS. Det finns dock också skillnader. Hibernate försöker dölja det verkliga arbetet med databasen så mycket som möjligt, så dessa Hibernate Cascades handlar exakt om Entity-objekt.

6.2 CascadeType

Kaskadparametern beskriver vad som ska hända med beroende objekt om vi ändrar deras förälder (huvudobjekt). Oftast används denna parameter tillsammans med anteckningar som beskriver objektberoende:

Exempel:

OneToOne(cascade = CascadeType.ALL)

Eller så här:

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

Det kan också skrivas som en separat anteckning:

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

Låt oss nu prata mer om vad dessa kommentarer betyder.

6.3 ALLA, HÅLLBAR, SAMMAN

CascadeType.ALLbetyder att alla åtgärder som vi utför med det överordnade objektet måste upprepas för dess beroende objekt.

CascadeType.PERSISTbetyder att om vi sparar det överordnade objektet till databasen, så måste samma sak göras med dess beroende objekt. Exempel:


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

Ett exempel på att arbeta med den här klassen:


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

Vi sparar endast ett objekt av typen Employee, dess beroende objekt EmployeeTask kommer att sparas i databasen automatiskt.

CascadeType.MERGEinnebär att om vi uppdaterar det överordnade objektet i databasen så måste samma sak göras med dess beroende objekt.

6.4 TA BORT, RADERA, LOSSA

CascadeType.REMOVEbetyder att om vi tar bort ett överordnat objekt i databasen så måste samma sak göras med dess beroende objekt.

CascadeType.DELETEbetyder detsamma. Dessa är synonymer. Bara från olika specifikationer.

CascadeType.DETACHbetyder att om vi tar bort det överordnade objektet från sessionen så måste samma sak göras med dess beroende objekt. Exempel:


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

Ett exempel på att arbeta med den här 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.REFRESHoch CascadeType.SAVE_UPDATEfungerar på samma sätt som vi förväntar oss - de duplicerar de åtgärder som utförs med det överordnade objektet till dess beroende objekt.

6.5 Alternativ för borttagning av föräldralösa barn

Ibland kan du också stöta på parametern orphan. Detta är en förkortning för Orphan removal. Det används för att säkerställa att det inte finns några underordnade enheter utan överordnade enheter.

OneToOne(orphan = true)

Om den här parametern är inställd på sant kommer den underordnade enheten att tas bort om den har försvunnitalla länkar. Det är inte exakt samma som Cascade.REMOVE.

Du kan ha en situation där flera föräldraenheter hänvisar till ett barn. Då är det fördelaktigt att den inte raderas tillsammans med borttagningen av moderenheten, utan bara om alla referenser till den upphävs.

Låt oss säga att du har en klass:


@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 kommer att raderas eftersom det inte finns några referenser kvar till det. Samtidigt tog ingen bort det överordnade objektet.

6.6 hämtningsalternativ

Hämta-alternativet låter dig styra hur beroende objekt laddas. Det tar vanligtvis ett av två värden:

  • FetchType.LAZY
  • FetchType.EAGER

Det här är ett mycket intressant ämne med olika fallgropar, så det är bäst att jag pratar om det i en separat föreläsning.