Vaadin 和 Hibernate - 正确关闭与数据库的连接

Posted

技术标签:

【中文标题】Vaadin 和 Hibernate - 正确关闭与数据库的连接【英文标题】:Vaadin and Hibernate - Close connection to database correctly 【发布时间】:2012-04-10 07:20:37 【问题描述】:

我目前遇到了一个有趣的问题。

我的情况:

我目前正在开发一个 Web 服务(我正在使用 VAADIN 在 Eclipse 中使用 JAVA 进行编程) 我的数据库是java derby 我正在为我的数据库使用休眠 我目前正在 Tomcat v7.0 上部署它

我的问题:

当我更改代码中的某些内容时(不管怎样),服务器应该重新加载它而无需重新启动 - 我想这是整体预期的行为 服务器重新加载应用程序成功,但如果我尝试点击某些东西(所以在重新加载之后),例如登录按钮,我得到一个错误

错误信息:

原因:org.hibernate.exception.GenericJDBCException:无法打开 connection] 与根本原因 ERROR XSDB6: Derby 的另一个实例可能 已经启动了数据库 C:\html-Ausgabe\database\DocumentDB。 在 org.apache.derby.iapi.error.StandardException.newException(未知 来源)...

我对此的看法

似乎在重新加载过程中,休眠的连接/上下文不会被破坏/关闭,因此当服务器尝试重新连接到数据库时会发生错误

我的代码

我有一个类,叫 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>

我做了研究,也在hibernate论坛上发帖(仍然没有一个答案:(),现在在这个网站上没有找到匹配的主题。所以我希望我没有做错什么。

如果你们中的任何人能以某种方式帮助我,我会非常高兴。目前我不知道要改变什么来阻止这个错误的发生。当然,如果我更改了一行代码,当我的应用程序在互联网上时,我不能总是重新启动整个服务器。

非常感谢您与我分享的每一个答案和想法。

【问题讨论】:

【参考方案1】:

快速而肮脏的解决方案:快速而肮脏的临时解决方案可能只是将 ?restartApplication 附加到您的 Vaadin 应用程序链接的任何地方。

更好的解决方案:我建议在 Hibernate 中使用 session-per-request 模式。通过使用 Vaadin 的事务侦听器,您可以轻松确保会话在每个请求上都关闭,而不会用额外的逻辑污染我们的程序代码。

您将这些方法放在您的主应用程序方法中,然后在您的 init() 方法中执行 attachVaadinTransactionListener()。链接到下面的详细文章。

    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

【讨论】:

一个快速而肮脏的临时解决方案可能只是将 ?restartApplication 附加到您的 Vaadin 应用程序链接的任何地方。【参考方案2】:

我找到了解决问题的方法。

首先,这是一个 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。我希望有一天这对其他人有所帮助。非常感谢你的帮助。

【讨论】:

是的,当我在开发期间需要内存数据库时,我会使用 HyperSQL。从来没有给我问题。

以上是关于Vaadin 和 Hibernate - 正确关闭与数据库的连接的主要内容,如果未能解决你的问题,请参考以下文章

Vaadin:设计模式 [关闭]

Vaadin 中的休眠会话错误

带有 Vaadin 插件的 Grails,是正确的选择吗?

社交网络的 Vaadin 前端? [关闭]

为啥我的 vaadin 按钮显示不正确?

Vaadin Crud 用户界面。轴未正确排序