2011-09-02 18 views
20

Sto scrivendo un progetto semplice, un'app business scritta in Swing, che utilizza Hibernate per il back-end. Vengo da Spring, che mi ha dato modi semplici per usare l'ibernazione e le transazioni. Ad ogni modo sono riuscito a far funzionare Hibernate. Ieri, durante la scrittura del codice per eliminare un fagiolo da DB, ho ottenuto questo:Perché ottengo org.hibernate.HibernateException: No CurrentSessionContext configurato

org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions 

Il codice di eliminazione è semplicemente:

Session sess = HibernateUtil.getSession(); 
    Transaction tx = sess.beginTransaction(); 
    try { 
     tx.begin(); 
     sess.delete(ims); 
    } catch (Exception e) { 
     tx.rollback(); 
     throw e; 
    } 
    tx.commit(); 
    sess.flush(); 

e il mio HibernateUtil.getSession() è:

public static Session getSession() throws HibernateException { 
     Session sess = null; 
     try { 
      sess = sessionFactory.getCurrentSession(); 
     } catch (org.hibernate.HibernateException he) { 
      sess = sessionFactory.openSession(); 
     } 
     return sess; 
    } 

aggiuntivo dettagli: non chiudo mai una sessione di ibernazione nel mio codice, solo alla chiusura dell'applicazione. È sbagliato? Perché ottengo questo su delete (solo per quel bean, altri funzionano), e non su altre operazioni (Insert, query, update)?

ho letto in giro e ho cercato di modificare il mio metodo getSession semplicemente in un sessionFactory.getCurrentSessionCall(), ma ho ottenuto: org.hibernate.HibernateException: No CurrentSessionContext configured!

Hibernat conf:

<hibernate-configuration> 
    <session-factory > 
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 
    <property name="hibernate.connection.url">jdbc:mysql://localhost/joptel</property> 
    <property name="hibernate.connection.username">root</property> 
    <property name="hibernate.connection.password">******</property> 
    <property name="hibernate.connection.pool_size">1</property> 
    <property name="show_sql">true</property> 
    <property name="hibernate.hbm2ddl.auto">update</property> 


    ..mappings.. 

    </session-factory> 
</hibernate-configuration> 
+0

Come appare il file di configurazione di sospensione? – Santosh

risposta

54

volevo chiederti una cosa, perché sei cercando di utilizzare il metodo "OpenSession"?

public static Session getSession() throws HibernateException {   
    Session sess = null;  
    try {   
     sess = sessionFactory.getCurrentSession(); 
    } catch (org.hibernate.HibernateException he) { 
     sess = sessionFactory.openSession();  
    }    
    return sess; 
} 

Non è necessario chiamare openSession(), perché getCurrentSession() metodo è sempre restituisce sessione corrente (Discussione nel caso se si è configurato per essere).

ho capito ... È necessario specificare contesto attuale nel file hibernate.cfg.xml

dovrebbe essere:!

<property name="hibernate.current_session_context_class">thread</property> 
10

No CurrentSessionContext configurato

Leggere la guida di riferimento su Contextual Sessions. Per questo è necessario il configure some provided or custom strategy. In un hibernate.cfg.xml, che ci si configurano con

<property name="hibernate.current_session_context_class">...</property> 

Si sarebbe probabilmente desidera utilizzare "filo" come valore per ottenere le sessioni per-thread. Quando si utilizza Spring, lo imposta automaticamente su SpringSessionContext, consentendo a Spring di integrare facilmente Hibernate con il proprio framework di gestione delle transazioni.

Vengo da Spring, che mi ha dato modi semplici per utilizzare l'ibernazione e le transazioni.

Se hai familiarità con Spring, perché non lo stai utilizzando per gestire Hibernate qui? Devi già sapere come lo rende semplice e infallibile.

Non chiudere mai una sessione di sospensione nel mio codice, solo alla chiusura dell'applicazione. È sbagliato?

Sì, questo è molto sbagliato. Ogni sessione non chiusa è una connessione di database aperta, quindi la tua app sta attualmente collegando le emorragie.

illegale tentativo di associare una collezione con due sessioni aperte

Ciò significa esattamente quello che dice. Hai provato a eseguire un'operazione di persistenza (save(), update(), delete()) su qualcosa che era già associato a una sessione diversa. Questo è ciò che accadrà quando si apriranno casualmente nuove sessioni ogni volta, che è ciò che accade poiché SessionFactory.getCurrentSession() fallirà sempre quando non è impostato "contesto di sessione corrente". In generale, mai apre una sessione solo perché uno non era già lì. È necessario disporre di strategie ben definite per l'apertura e la chiusura delle sessioni e non lasciare mai nulla aprire una sessione al di fuori di queste "strategie". Questo è un percorso sicuro per perdite di risorse ed errori come quello che hai incontrato.

3

Ho affrontato lo stesso problema quando sto lavorando su un portale in cui utilizzo il servizio di invio a molla con ibernazione. Questo tipo di problema si verifica solo se il metodo del servizio chiamato contiene più chiamate DAO che colpiscono il database con la sessione di sospensione.

E la soluzione è impostata l'annotazione @Transaction per quei metodi con più chiamate DAO. (Implica che tutte le chiamate DOA con questo metodo debbano essere contenute in un'unica transazione.)

Problemi correlati