Modifiche a cascata

Disponibile

6.1 Gestione profonda delle dipendenze

E alcune cose più utili e interessanti sulle annotazioni @OneToMany e simili. Tutti hanno 4 opzioni comunemente usate:

  • cascata = CascadeType.ALL
  • orphanRemoval = vero
  • fetch = FetchType.LAZY

Ora li analizzeremo in modo più dettagliato. E inizieremo con il più interessante - CascadeType . Questo parametro determina cosa dovrebbe accadere alle entità dipendenti se cambiamo l'entità principale.

La specifica JPA ha i seguenti valori per questo parametro:

  • TUTTO
  • PERSISTERE
  • UNISCI
  • RIMUOVERE
  • RICARICARE
  • STACCARE

Tuttavia, Hibernate espande questa specifica in altre tre opzioni:

  • REPLICARE
  • SALVA_AGGIORNA
  • SERRATURA

C'è, ovviamente, un forte parallelo con il database e il loro CONSTRANIS. Tuttavia, ci sono anche differenze. Hibernate cerca di nascondere il più possibile il vero lavoro con il database, quindi questi Hibernate Cascades riguardano esattamente gli oggetti Entity.

6.2 Tipo Cascata

Il parametro cascade descrive cosa dovrebbe accadere agli oggetti dipendenti se cambiamo il loro genitore (oggetto principale). Molto spesso, questo parametro viene utilizzato insieme alle annotazioni che descrivono le dipendenze degli oggetti:

Esempio:

OneToOne(cascade = CascadeType.ALL)

O così:

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

Può anche essere scritto come annotazione separata:

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

Ora parliamo di più sul significato di queste annotazioni.

6.3 TUTTO, PERSISTERE, UNIRE

CascadeType.ALLsignifica che tutte le azioni che eseguiamo con l'oggetto genitore devono essere ripetute per i suoi oggetti dipendenti.

CascadeType.PERSISTsignifica che se salviamo l'oggetto genitore nel database, lo stesso deve essere fatto con i suoi oggetti dipendenti. Esempio:

@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;

   @OneToOne(cascade = CascadeType.PERSIST, mappedBy="task")
   private EmployeeTask task;
}

Un esempio di lavoro con questa classe:

Employee director = new Employee();
EmployeeTask task = new EmployeeTask();
director.task = task;

session.persist(director);
session.flush();

Salviamo solo un oggetto di tipo Employee, il suo oggetto dipendente EmployeeTask verrà salvato automaticamente nel database.

CascadeType.MERGEsignifica che se aggiorniamo l'oggetto padre nel database, lo stesso deve essere fatto con i suoi oggetti dipendenti.

6.4 RIMUOVERE, CANCELLARE, STACCARE

CascadeType.REMOVEsignifica che se eliminiamo un oggetto genitore nel database, lo stesso deve essere fatto con i suoi oggetti dipendenti.

CascadeType.DELETEsignifica lo stesso. Questi sono sinonimi. Solo da specifiche diverse.

CascadeType.DETACHsignifica che se rimuoviamo l'oggetto genitore dalla sessione, lo stesso deve essere fatto con i suoi oggetti dipendenti. Esempio:

@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;

   @OneToOne(cascade = CascadeType.DETACH, mappedBy="task")
   private EmployeeTask task;
}

Un esempio di lavoro con questa classe:


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.REFRESHe CascadeType.SAVE_UPDATEfunzionano nello stesso modo in cui ci aspettiamo: duplicano le azioni eseguite con l'oggetto genitore sul suo oggetto dipendente.

6.5 Opzione di rimozione degli orfani

Inoltre a volte potresti imbatterti nel parametro orphan. Questo è l'abbreviazione di rimozione degli orfani. Viene utilizzato per garantire che non vi siano entità figlio senza entità padre.

OneToOne(orphan = true)

Se questo parametro è impostato su true, l'entità figlio verrà eliminata se è scomparsatutti i collegamenti. Non è esattamente lo stesso di Cascade.REMOVE.

Potresti avere una situazione in cui diverse entità padre fanno riferimento a un figlio. Quindi è vantaggioso che non venga eliminato insieme alla cancellazione dell'entità madre, ma solo se tutti i riferimenti ad esso vengono annullati.

Diciamo che hai una classe:

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

L'oggetto EmployeeTask verrà eliminato perché non sono rimasti riferimenti ad esso. Allo stesso tempo, nessuno ha eliminato l'oggetto padre.

6.6 opzione di recupero

L'opzione fetch consente di controllare come vengono caricati gli oggetti dipendenti. Di solito assume uno dei due valori:

  • FetchType.LAZY
  • FetchType.EAGER

Questo è un argomento molto interessante con varie insidie, quindi è meglio che ne parli in una lezione separata.

Commenti
  • Popolari
  • Nuovi
  • Vecchi
Devi avere effettuato l'accesso per lasciare un commento
Questa pagina non ha ancora commenti