Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    Strano comportamento Hibernate

    Ciao a tutti,
    allora: ho un'applicazione che funge da WebService che esegue le operazioni CRUD su mysql, il webService è usato da delle applicazioni mobile. Poi ne ho un'altra fatto con String3 che fa sempre operazioni CRUD sullo stesso DB ed è un portale Web.
    Il problema è che quando faccio delle modifiche dal Portale web, sul db le modifiche vengono eseguite correttamente, ma dal webService non si vedono. Se riavvio tomcat magicamente sono visibili anche dal webService.

    Perche accade tutto ciò???
    Grazie a tutti

  2. #2
    Utente di HTML.it L'avatar di Alex'87
    Registrato dal
    Aug 2001
    residenza
    Verona
    Messaggi
    5,802
    Ma le modifiche sono seguite ogni volta da un commit?
    SpringSource Certified Spring Professional | Pivotal Certified Enterprise Integration Specialist
    Di questo libro e degli altri (blog personale di recensioni libri) | ​NO M.P. TECNICI

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    O, parlando in termini di EntityManager, viene fatto il flush()?


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  4. #4
    Le operazioni avvengono in questo modo dal portale

    codice:
    @Autowired    private SessionFactory sessionFactory;
        
        private Session getCurrentSession() {
            return sessionFactory.getCurrentSession();
        }
    
    
        public void addContenuto(Contenuto contenuto) {
            getCurrentSession().save(contenuto);
        }
    
    
        public void updateContenuto(Contenuto contenuto) {
            getCurrentSession().update(contenuto);
            
        }

    e vengono recuperate dal webService in questo modo
    codice:
    public List<Contenuto> findContenutoByIdUtente(Integer idUtente) {        
    EntityManager em = getEntityManager();
            try {
                Query query = em.createNamedQuery("Contenuto.findByIdUtente");
                query.setParameter("idUtente", idUtente);
    
    
                return query.getResultList();
            } finally {
                em.close();
            }
        }

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Tu parli genericamente di "modifiche".
    Domanda: se dal portale effettui una INSERT, il WebService la vede?
    Perchè, se le cose stanno come penso (che le INSERT le vede, ma le UPDATE/DELETE no), allora significa solo che stai usando "male" Hibernate (o, più in generale, JPA).

    Verifica se il WebService sbaglia solo con le UPDATE/DELETE o se sbaglia anche con le INSERT.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Praticamente le operazioni crud dal portale funzionano tranquillamente. Dal WebService non vedo le modifiche, sembra che legga da un'altro db. Se faccio la modifica direttamente sul database, dal portale vedo le modifiche, da WebService no.

  7. #7
    Allora, credo di aver capito qualcosa. Il problema dovrebbe essere una cache che si trova tra hibernate e il db. Adesso come faccio a svuotare questa cache o anche a non usarla proprio? in rete tutti dicono di fare flush(), ma mi va in eccezione. Io lo messo prima di em.close()

  8. #8
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Io ti avevo fatto una domanda ben precisa (alla quale non hai risposto) ed il motivo era proprio per questo: Hibernate (o, meglio, JPA in generale) fa uso dell'EntityManager per manipolare i dati del DB. L'EntityManager è a tutti gli effetti una "cache" e non vi si può rinunciare: quando LEGGI un oggetto dal DB, questo entra a far parte del context (diventa "managed"). E lì rimane (se non espressamente rimossa) per tutto il tempo di vita del context.

    Tutto parte dalla LETTURA (ovvero, da una query o dall'uso del metodo find()). Spiegazione in soldoni:

    1) Viene richiesto un determinato oggetto (per mezzo del find() tramite chiave o per mezzo di una query).
    2) Per prima cosa, l'EntityManager cerca l'oggetto nel context (la cache). Se lo trova, lo restituisce.
    3) Se l'oggetto non viene trovato nel context, viene cercato nel DB.
    4) Se viene trovato nel DB, questo oggetto viene reperito ed inserito nel context.
    5) Tutte le modifiche che vengono fatte ad un oggetto managed (merge() e remove(), la persist() in teoria dovrebbe fare automaticamente la persistenza) vengono fatte solo nel context.
    6) Per rendere persistenti le modifiche sul DB è necessario "sincronizzare" il context col DB: flush().
    7) Non c'è scritto da nessuna parte (che io sappia) che l chiusura del EntityManager forzi una sincronizzazione (anche perchè, a livello generale, potrebbe non essere affatto una buona cosa: vedi transazioni attive).

    Il punto focale è il 2: se l'oggetto è già stato letto dal DB (quindi è "managed"), la copia che ti viene restituita è quella attualmente presente nel context (che può essere completamente diversa da quella presente nel DB). Per ovviare a questo "problema" ci sonotre strade:

    1) Effettuare un flush() per sincronizzare i dati col DB. Attenzione: i dati presenti nel context sostituiscono quelli presenti nel DB. Questa è un'operazione che dovrebbe fare CHI SCRIVE!

    2) Marcare come "detached" le entità DOPO che sono state usate e non si intende ri-utilizzarle se non "refreshate": vedi metodo detach(). Il metodo detach() rende l'entità "unmanaged" (quindi, svincolata dal context). Per farla ritornare nel context è necessario usare il merge(). Questa è un'operazione che dovrebbe fare CHI LEGGE e basta.

    3) Richiamare un refresh() sull'entità che si desidera ri-leggere dal DB (perdendo eventuali modifiche fatte e non sincronizzate).

    Ciao.
    Ultima modifica di LeleFT; 10-04-2014 a 16:42
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  9. #9
    Mi potreste indicare come usare il em.flush(); in questo metodo?

    codice:
        public List<Prodotti> getProdottoByIdAzienda(Integer idAzienda){        
          EntityManager em = getEntityManager();
            try {
                Query q = em.createNamedQuery("Prodotti.findByIdUtentePubblicati");
                q.setParameter("idUtente", idAzienda);
                return q.getResultList();
            } finally {
                em.close();
            }
        }
    ovunque lo metto mi va in eccezione

  10. #10
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Il flush() in quel contesto non ti serve a nulla: stai facendo una query di selezione. Il flush() (e l'ho scritto) serve a sincronizzare i dati del DB con quelli che sono nel context attualmente... in pratica, serve A CHI SCRIVE (cioè, chi fa operazioni di INSERT/UPDATE/DELETE).

    Poi, dici che ti va in eccezione, ma non posti nemmeno uno straccio di stackTrace... che ne sappiamo noi di che eccezione viene sollevata? La prima causa che mi viene in mente è che tu stia eseguendo un flush() senza che vi sia una transazione attiva... ma, appunto, se stai leggendo non hai bisogno di una transazione attiva.

    Documentandomi meglio, ho visto che c'è la possibilità di dire al EntityManager di non usare la cache:
    http://docs.oracle.com/javaee/6/tutorial/doc/gkjjj.html

    Ed è anche possibile specificare che un'intera Entity non sia messa in cache, tramite l'annotation Cacheable(false)


    Quindi, o specifichi

    codice:
    <shared-cache-mode>NONE</shared-cache-mode>

    nel persistence.xml, oppure disabiliti la cache per una (o più) particolare Entity.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.