Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 28 di 68
  • livello ninja
Indice lezioni

Ciclo di vita di un'Entity

Analizziamo il ciclo di vita di un'Entity proponendo l'esempio pratico di una prenotazione con contestuale registrazione in un sistema di booking online.
Analizziamo il ciclo di vita di un'Entity proponendo l'esempio pratico di una prenotazione con contestuale registrazione in un sistema di booking online.
Link copiato negli appunti

Nel capitolo precedente abbiamo introdotto le operazioni di persistenza fondamentali. L'effetto di queste
azioni può essere modellato con un automa a stati finiti che fornisce una visione grafica del ciclo di vita di
un'Entity:

Figura 1. Entity lifecycle
Entity lifecycle

Quando una istanza di Entity è creata con l'operatore new() di Java, si trova nello stato New, l'EntityManager non è ancora
a conoscenza della sua esistenza e l'oggetto non è sotto il suo controllo. Nel momento in cui eseguiamo un'operazione
di persist(), merge() o refresh() sull'istanza dell'Entity, oppure la recuperiamo con find(), utilizzando l'EntityManager in un contesto transazionale,
l'istanza Entity passa nello stato Managed e rimane sotto il controllo dell'EntityManager (attached) per un tempo
pari alla vita del persistence context.

Il persistence context dell'EntityManager può essere limitato alla durata di un singolo metodo
di un session bean o avere una lunghezza di tempo arbitraria. Un'Entity passa nello stato detached anche a seguito di clonazione o serializzazione
dell'oggetto.

Un persistence context può essere di due tipi: transaction-scoped o extended. Per un EntityManager associato ad un persistence
context
di tipo transaction-scoped le Entity passano automaticamente nello stato detached al termine della transazione. Quando eseguiamo
un metodo di un session bean stateless con il supporto transazionale, tutti gli oggetti Entity utilizzati all'interno del metodo sono
in stato attached. Non appena il metodo termina anche la transazione si conclude con un commit o rollback e l'EntityManager si assicura
che lo stato delle Entity sia sincronizzato con il database. Le Entity passano quindi nello stato detached, non sono
più sotto il controllo dell'EntityManager.

Un persistence context di tipo extended
è caratterizzato dal fatto che il suo tempo di vita si estende su più transazioni e può essere utilizzato solo all'interno di session beans stateful. In sostanza
il tempo di vita coincide in questo caso con il tempo di vita del bean stateful. Per definire un persistence context di tipo extended, si
può utilizzare l'attributo type dell'annotation @PersistenceContext, in un bean stateful:

..
  @PersistenceContext(type=PersistenceContextType.EXTENDED)
  EntityManager entityManager;
  ..

Analizziamo adesso più in dettaglio le operazioni di persistenza con un occhio agli effetti sulle relazioni. Per esempio, supponiamo di voler registrare
un utente contestualmente alla sua prima prenotazione e aggiungiamo un metodo per questa funzionalità all'interfaccia CustomerService:

..
  void firstBooking(Customer customer, Booking booking, Room room);
  ..

E la seguente implementazione all'interno della classe bean CustomerServiceBean:

..
  @Override
  public void firstBooking(Customer customer, Booking booking, Room room) {
		entityManager.persist(customer);
		booking.setCustomer(customer);
		booking.setRoom(room);
		entityManager.persist(booking);
  }
  ..

Il metodo effettua prima la persistenza dell'oggetto customer che entra a far parte del persistence context transaction-scoped della transazione
corrente, successivamente gli oggetti customer e room vengono settati sull'oggetto booking aggiornando lato object-oriented la relazione
che intercorre tra booking, customer e room.

Infine si effettua la persistenza dell'oggetto booking. Ciò che si ottiene a livello di statement
SQL è la creazione ed esecuzione di un INSERT sulla tabella CUSTOMER ed uno sulla tabella BOOKING con foreign-key verso la tabella CUSTOMER che punta
al record customer appena creato, e la foreign key verso ROOM che punta al record già esistente.

Al termine del metodo, viene eseguito il commit della transazione
da parte dell'EntityManager con gli oggetti customer e booking che passano allo stato detached.
Se non avessimo effettuato la preliminare persistenza dell'oggetto customer, avremmo avuto il seguente errore:

Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance -
 save the transient instance before flushing : it.html.model.hotel.Booking.customer -> it.html.model.hotel.Customer

Il motivo è che il comportamento di default è di non propagare le operazioni di persistenza alle Entity relazionate con
quella corrente. Le annotation di relazione consentono di attivare l'operazione di Cascade attraverso
l'attributo cascade come vedremo nel successivo capitolo.

Ti consigliamo anche