2012-03-26 14 views
6

Attualmente sto riscontrando un problema interessante.Vaadin e Hibernate - Chiudi correttamente il database

mia situazione:

  • Attualmente sto sviluppando un servizio web (sto usando Vaadin per la programmazione con JAVA in Eclipse)
  • mio database dietro è Java derby
  • sto usando hibernate per la mia base di dati
  • attualmente sto distribuirlo su Tomcat v7.0

mio problema:

  • Quando cambio qualcosa nel mio codice (non importa cosa), il server dovrebbe ricaricarlo senza il bisogno di essere riavviato - Direi che è il comportamento previsto complessiva
  • Il il server ricarica l'applicazione con successo, ma se provo a fare clic su qualcosa (quindi dopo il ricaricamento), ad es il login-Button, ottengo un errore

messaggio di errore:

Causa: org.hibernate.exception.GenericJDBCException: Impossibile aprire collegamento] con root cause ERRORE XSDB6: Un altro caso di Derby hanno già avviato il database C: \ HTML-Ausgabe \ database \ DocumentDB. a org.apache.derby.iapi.error.StandardException.newException (Sconosciuto Source) ...

I miei pensieri su questo

Sembra che in qualche modo sul processo di ricarica la connessione/contesto di ibernazione non ottiene distrutto/chiuso e quindi l'errore occures quando il server tenta di riconnettersi al database

My Code

Ho una classe, denominata Hibernate Listener:

public class HibernateListener implements ServletContextListener { 

    public void contextInitialized(ServletContextEvent event) { 
     HibernateUtil.getSessionFactory(); // Just call the static initializer of that class  
    } 

    public void contextDestroyed(ServletContextEvent event) { 
     HibernateUtil.getSessionFactory().close(); // Free all resources 
    } 
} 

mio hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC 
     "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
    <session-factory> 
     <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property> 
     <property name="hibernate.connection.url">jdbc:derby:C:\HTML-Ausgabe\database\DocumentDB;create=true</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.DerbyDialect</property> 
     <property name="hibernate.current_session_context_class">thread</property> 
     <property name="hibernate.hbm2ddl.auto">create-drop</property> 
     <property name="hibernate.show_sql">true</property> 

     <mapping class="view.model.database.User"/> 
     <mapping class="view.model.database.Document"/> 
     <mapping class="view.model.database.Version"/> 
     <mapping class="view.model.database.VersionData"/> 
    </session-factory> 
</hibernate-configuration> 

mio (Vaadin) web.xml, in cui ho aggiunto un "ascoltatore" per il superiore mostrato HibernateListener (controllare il testo a chi ascolta):

<?xml version="1.0" encoding="UTF-8"?> 
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 
    <display-name>Bachelorprojekt</display-name> 
    <context-param> 
     <description>Vaadin production mode</description> 
     <param-name>productionMode</param-name> 
     <param-value>false</param-value> 
    </context-param> 
    <servlet> 
     <servlet-name>Bachelorprojekt Application</servlet-name> 
     <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class> 
     <init-param> 
      <description>Vaadin application class to start</description> 
      <param-name>application</param-name> 
      <param-value>view.view.WebsiteFrame</param-value> 
     </init-param> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>Bachelorprojekt Application</servlet-name> 
     <url-pattern>/*</url-pattern> 
    </servlet-mapping> 

    <listener> 
     <listener-class>view.model.database.HibernateListener</listener-class> 
    </listener> 
    <welcome-file-list> 
     <welcome-file>index.html</welcome-file> 
     <welcome-file>index.htm</welcome-file> 
     <welcome-file>index.jsp</welcome-file> 
     <welcome-file>default.html</welcome-file> 
     <welcome-file>default.htm</welcome-file> 
     <welcome-file>default.jsp</welcome-file> 
    </welcome-file-list> 
</web-app> 

ho fatto ricerche, pubblicato anche sul forum di sospensione (ancora senza nemmeno una sola risposta :() e ora non ha trovato un tema di corrispondenza su questo w ebsite. Quindi spero di non aver fatto qualcosa di sbagliato.

Se qualcuno di voi mi potrebbe aiutare in qualche modo, sarei davvero felice. Attualmente non so cosa cambiare per fermare questo errore. E, naturalmente, non posso sempre riavviare l'intero server più tardi quando la mia applicazione è su Internet, se cambio una riga di codice.

Grazie mille per ogni risposta e ho pensato che stai condividendo con me.

risposta

4

ho trovato la soluzione al mio problema.

Prima di tutto, è stato un problema di Apache Derby, come ho costretto a chiudere con

public void contextDestroyed(ServletContextEvent event) { 
    HibernateUtil.getSessionFactory().close(); // Free all resources 
    try { 
      DriverManager.getConnection("jdbc:derby:;shutdown=true"); 
    } catch (SQLException e) {} 
    } 
} 

ha funzionato bene per me.

Ora ho spostato il mio database vom apache derby su mysql e ho notato che il problema, descritto nella mia domanda sopra, non si verificava più.

Quindi, lezione appresa: non utilizzare derby Apache. Spero che questo aiuti qualcun altro un giorno. Grazie mille per il vostro aiuto.

+0

Sì, utilizzo HyperSQL quando ho bisogno di un DB in memoria durante lo sviluppo. Non mi ha mai dato problemi. – anataliocs

2

Soluzione rapida e sporca: Una soluzione temporanea rapida e sporca potrebbe essere solo aggiungere Appendice a qualsiasi applicazione Vaadin collegata.

Soluzione migliore: Si consiglia di utilizzare il modello sessione per richiesta con Hibernate. Usando il listener delle transazioni di Vaadin puoi facilmente assicurarti che la sessione sia chiusa su ogni richiesta senza inquinare il nostro codice di programma con logica aggiuntiva.

Si posizionano questi metodi nel metodo di applicazione principale e quindi si esegue attachVaadinTransactionListener() nel metodo init(). Link all'articolo dettagliato su questo sotto.

private void attachVaadinTransactionListener() { 
    getContext().addTransactionListener(new TransactionListener() { 
     public void transactionEnd(Application application, 
       Object transactionData) { 
      // Transaction listener gets fired for all (Http) sessions 
      // of Vaadin applications, checking to be this one. 
      if (application == EnpApplication.this) { 
       closeSession(); 
      } 
     }   

     public void transactionStart(Application application, 
       Object transactionData) { 
     } 
    }); 
} 

private void closeSession() { 
    Session sess = HibernateUtil.getSessionFactory().getCurrentSession(); 
    if (sess.getTransaction().isActive()) {   
     sess.getTransaction().commit(); 

     if(sess.isOpen()) { sess.flush(); } 
    } 
    if(sess.isOpen()) {   
     sess.close(); 
    } 
} 

Hibernate with Vaadin

+0

Una soluzione temporanea rapida e sporca potrebbe essere quella di aggiungere? RestartApplication a ovunque l'applicazione Vaadin è collegata. – anataliocs