Sto usando SEAM con JPA (implementato come Seam Managed Persistance Context), nel mio backing bean carico una raccolta di entità (ArrayList) nel backing bean.Forza aggiornamento della raccolta JPA entityManager
Se un altro utente modifica una delle entità in una sessione diversa Voglio che questi cambiamenti siano propagate alla raccolta in mia sessione, ho un metodo di refreshList()
e provato quanto segue ...
@Override
public List<ItemStatus> refreshList(){
itemList = itemStatusDAO.getCurrentStatus();
}
Con la seguente query
@SuppressWarnings("unchecked")
@Override
public List<ItemStatus> getCurrentStatus(){
String s = "SELECT DISTINCT iS FROM ItemStatus iS ";
s+="ORDER BY iS.dateCreated ASC";
Query q = this.getEntityManager().createQuery(s);
return q.getResultList();
}
Re-esecuzione della query, questo restituisce solo gli stessi dati ho già (suppongo che sta usando la cache di 1 ° livello, piuttosto che colpire il database)
@Override
public List<ItemStatus> refreshList(){
itemStatusDAO.refresh(itemList)
}
Calling entityManager.refresh()
, questo dovrebbe aggiornare dal database tuttavia ottengo un'eccezione javax.ejb.EJBTransactionRolledbackException: Entity not managed
quando uso questo, normalmente io userei entityManager.findById(entity.getId)
prima di chiamare refresh() per assicurarsi che sia collegato al PC, ma come sto rinfrescanti una raccolta di entità non posso farlo.
Sembra un problema abbastanza semplice, non riesco a credere che non ci sia modo di forzare JPA/hibernate per bypassare la cache e colpire il database ?!
TEST AGGIORNAMENTO CASO:
Sto utilizzando due browser diversi (1 e 2) per caricare la stessa pagina web, faccio una modifica in 1 che aggiorna un attributo booleano in una delle entità ItemStatus, la vista viene aggiornato per 1 per visualizzare l'attributo aggiornato, controllo il database tramite PGAdmin e la riga è stata aggiornata. Quindi premere Aggiorna nel Browser 2 e l'attributo non è stato aggiornato
Ho provato a utilizzare il seguente metodo per unire tutte le entità prima di chiamare .refresh, ma le entità non erano ancora aggiornate dal database.
@Override
public void mergeCollectionIntoEntityManager(List<T> entityCollection){
for(T entity: entityCollection){
if(!this.getEntityManager().contains(entity)){
this.getEntityManager().refresh(this.getEntityManager().merge(entity));
}
}
}
Hai unificato gli oggetti nel gestore di entità prima di chiamare l'aggiornamento? – Perception
No, non l'ho fatto, il metodo merge() non accetta collezioni e pensavo che chiamarlo su ogni membro della collezione fosse un po 'eccessivo? – DaveB
Potrebbe essere, se si dispone di una lista davvero grande. Ma le normali fusioni sincronizzano semplicemente lo stato dell'oggetto con l'unità di lavoro dei gestori di entità e sono molto veloci. Se la fusione impiega troppo tempo, puoi sempre avviare tutto dalla cache di secondo livello con 'entityMgr.getEntityManagerFactory(). GetCache(). EvictAll()'. – Perception