Vaadin и Hibernate - Правильно закрыть соединение с базой данных

В настоящее время у меня возникает интересная проблема.

Моя ситуация:

  • В настоящее время я занимаюсь разработкой веб-сервиса (я использую VAADIN для программирования с JAVA в eclipse).
  • Моя база данных - это java derby
  • Я использую hibernate для моей базы данных
  • В настоящее время я размещаю его на Tomcat v7.0

Моя проблема:

  • Когда я что-то меняю в своем коде (не важно, что), сервер должен перезагрузить его без необходимости перезапуска - я думаю, что общее ожидаемое поведение
  • Сервер перезагружает приложение успешно, но если я попытаюсь щелкнуть что-нибудь (так после перезагрузки), например, кнопка входа в систему, я получаю сообщение об ошибке

Сообщение об ошибке:

Причина: org.hibernate.exception.GenericJDBCException: не удалось открыть соединение] с основной причиной ERROR XSDB6: другой экземпляр Derby может уже загрузили базу данных C:\HTML-Ausgabe\database\DocumentDB.   at org.apache.derby.iapi.error.StandardException.newException(Неизвестно Источник)...

Мои мысли на этом

Кажется, что каким-то образом в процессе перезагрузки соединение/контекст в hibernate не уничтожается/закрывается, и поэтому ошибка возникает, когда сервер пытается подключиться к базе данных

Мой код

У меня есть класс, называемый 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
 }
}

Мой hibernate.cfg.xml:

<!--?xml version="1.0" encoding="UTF-8"?-->
<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>
 <mapping>
 <mapping>
 <mapping>
 </mapping></mapping></mapping></mapping></session-factory>
</hibernate-configuration>

My (VAADIN) web.xml, в котором я добавил "прослушиватель" для верхнего показанного HibernateListener (проверьте текст на слушателе):

<!--?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>

Я занимался исследованиями, размещенными также на форуме hibernate (по-прежнему без единого ответа:() и теперь не нашел подходящую тему на этом веб-сайте. Поэтому я надеюсь, что я не сделал что-то неправильно.

Если бы кто-нибудь из вас мог мне помочь, я был бы действительно счастлив. В настоящее время я не знаю, что изменить, чтобы остановить эту ошибку. И, конечно же, я не могу перезапустить весь сервер позже, когда мое приложение находится в Интернете, если я изменю одну строку кода.

Большое спасибо за каждый ответ и подумал, что вы делитесь со мной.

2 ответа

Я нашел решение своей проблемы.

Прежде всего, это была проблема с дерби в Apache, поскольку я заставил ее закрыть с помощью

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

это сработало для меня.

Теперь я перекопал свою базу данных vom apache derby в mysql и заметил, что проблема, описанная в моем вопросе выше, больше не встречается.

Итак, извлеченный урок: Не используйте apache derby. Надеюсь, это когда-нибудь поможет кому-то другому. Большое спасибо за вашу помощь.


Быстрое и грязное решение: Быстрое и грязное временное решение может быть просто добавлено? restartApplication везде, где связано ваше приложение Vaadin.

Лучшее решение: Я рекомендую использовать шаблон сеанса за запрос с Hibernate. Используя прослушиватель транзакций Vaadin, вы можете легко убедиться, что сеанс закрыт по каждому запросу, не загрязняя наш программный код дополнительной логикой.

Вы помещаете эти методы в свой основной метод приложения, а затем выполняете attachVaadinTransactionListener() в вашем методе init(). Ссылка на подробную статью по этому вопросу ниже.

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();
 }
}

Спящий режим с Ваадином

licensed under cc by-sa 3.0 with attribution.