Vaadin и Hibernate - правильно закрыть соединение с базой данных - PullRequest
6 голосов
/ 26 марта 2012

У меня сейчас интересная проблема.

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

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

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

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

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

Причина: org.hibernate.exception.GenericJDBCException: не удалось открыть соединение] с первопричиной ОШИБКА XSDB6: другой экземпляр Derby может уже загрузили базу данных C: \ HTML-Ausgabe \ database \ DocumentDB. в 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"?>
<!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>

Мой (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>

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

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

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

Ответы [ 2 ]

4 голосов
/ 23 апреля 2012

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

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

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. Я надеюсь, что это поможет кому-то еще когда-нибудь. Большое спасибо за вашу помощь.

2 голосов
/ 05 апреля 2012

Быстрое и грязное решение: Быстрое и грязное временное решение может быть просто добавить? 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();
    }
}

Hibernate с Vaadin

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...