G.Morreale
Introduzione:
Come ho accennato nel precedente articolo se si usa un EntityManager JTA la transazione è delimitata dall'inizio e fine di un metodo.
L'istruzione dell'EntityManager sulla quale vorrei fare chiarezza è l'operazione di flush. (metodo EntityManager.flush())
La principale funzione del flush, senza scendere nei dettagli relativi alle relazioni tra Entity, è quella di sincronizzare il persistenceContext con il database sottostante.
L'EntityManager può avere due tipologie di FlushMode
FlushModeType.AUTO(Default) - Il flush avviene non appena viene eseguita una query in automatico
FlushModeType.COMMIT - Il flush avviene solo sul commit della transazione.
Esempio
Supponiamo di avere l'entity Esempiotable dotato di due campi (id, testo)
e di eseguire il seguente codice, con opportune varianti:
//FLUSHMODETYPE.COMMIT - Senza Flush
em.setFlushMode(FlushModeType.COMMIT);
Esempiotable es = em.find(Esempiotable.class, 1);
es.setTesto("ciao");
String nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
es = (Esempiotable) em.createQuery("SELECT Object(o) FROM Esempiotable o WHERE o.id = 1").getResultList().get(0);
nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
//em.flush(); LINEA COMMENTATA!!!!!
nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
Il codice precedente, usando come persistence provider hibernate, genera il seguente sql:
Hibernate:
select
esempiotab0_.id as id48_0_,
esempiotab0_.testo as testo48_0_
from
esempiotable esempiotab0_
where
esempiotab0_.id=?
ciao
Hibernate:
select
esempiotab0_.id as id48_,
esempiotab0_.testo as testo48_
from
esempiotable esempiotab0_
where
esempiotab0_.id=1
ciao
ciao
In sostanza disabilitando l'auto flushing e non chiamando esplicitamente il metodo flush non viene eseguita l'update che porterebbe alla modifica della riga corrispondente all'istanza dell'entity.
Nonostante ciò è possibile notare come il testo stampato sia sempre ciao perchè le modifiche anche se non riportate sul db sono ben presenti nel persistence context.
Altro caso:
//FLUSHMODETYPE.COMMIT - Con Flush
em.setFlushMode(FlushModeType.COMMIT);
Esempiotable es = em.find(Esempiotable.class, 1);
es.setTesto("ciao");
String nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
es = (Esempiotable) em.createQuery("SELECT Object(o) FROM Esempiotable o WHERE o.id = 1").getResultList().get(0);
nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
em.flush();
nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
Hibernate:
select
esempiotab0_.id as id36_0_,
esempiotab0_.testo as testo36_0_
from
esempiotable esempiotab0_
where
esempiotab0_.id=?
ciao
Hibernate:
select
esempiotab0_.id as id36_,
esempiotab0_.testo as testo36_
from
esempiotable esempiotab0_
where
esempiotab0_.id=1
ciao
Hibernate:
update
esempiotable
set
testo=?
where
id=?
ciao
In questo caso l'update viene eseguita solo quando viene richiamato esplicitamente il metodo di sincronizzazione con il db (flush()).
//FLUSHMODETYPE.AUTO - Con Flush
em.setFlushMode(FlushModeType.AUTO);
Esempiotable es = em.find(Esempiotable.class, 1);
es.setTesto("ciao");
String nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
es = (Esempiotable) em.createQuery("SELECT Object(o) FROM Esempiotable o WHERE o.id = 1").getResultList().get(0);
nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
em.flush();
nuovoTesto = es.getTesto();
System.out.println(nuovoTesto);
Hibernate:
select
esempiotab0_.id as id40_0_,
esempiotab0_.testo as testo40_0_
from
esempiotable esempiotab0_
where
esempiotab0_.id=?
ciao
Hibernate:
update
esempiotable
set
testo=?
where
id=?
Hibernate:
select
esempiotab0_.id as id40_,
esempiotab0_.testo as testo40_
from
esempiotable esempiotab0_
where
esempiotab0_.id=1
ciao
ciao
In questo caso l'update viene eseguito in automatico prima di eseguire una nuova query.
Il flush() richiamato esplicitamente in questo caso non deve provvedere alla sincronizzazione di null'altro, e quindi nello specifico esempio risulta inutile.
Conclusione
Un breve post per mostrare attraverso un esempio il comportamento del metodo flush in relazione al FlushModeType
No comments:
Post a Comment