【问题标题】:HSQL DB in Servlet: lock file not releasedServlet 中的 HSQL DB:锁定文件未释放
【发布时间】:2012-07-22 21:41:19
【问题描述】:

我在 Servlet 中运行 HSQLDB。当我将应用程序重新部署到 Web 服务器时,.lck 文件未正确释放,HSQL 服务器无法加载该文件。

Web 服务器是 NetBeans 附带的 Tomcat 7.0.22...

任何想法为什么会发生这种情况?

这是初始化代码:

@Override public void init() throws ServletException {
        HsqlProperties p = new HsqlProperties();
        p.setProperty("server.database.0", dbPath);
        p.setProperty("server.dbname.0", Environment.PERSISTENCE_HSQL_DB_NAME);
        p.setProperty("server.port", Environment.PERSISTENCE_HSQL_PORT);
        server = new Server();
        server.setProperties(p);
        server.setSilent(false);
        server.setTrace(true);
        server.setLogWriter(new PrintWriter(System.out));
        server.setErrWriter(null);
        server.start();

        server.checkRunning(true);

        /* Exception handling */
    }

这是我的关闭/销毁方法:

@Override
public void destroy() {
    super.destroy();
    server.setNoSystemExit(true);
    server.stop();
    server.shutdown();
    controller.shutdown();
}

我正在使用 JPA。如果数据库加载(首次启动),则应用程序运行正常。这是我的persistence.xml:

<persistence-unit name="embedded_hsql" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <!-- Entities -->
    <properties>
        <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
        <property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost:9001/fst_db;hsqldb.lock_file=false"/>
        <property name="hibernate.connection.username" value="SA"/>
        <property name="hibernate.connection.password" value=""/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
        <property name="hibernate.show_sql" value="false"/>
        <property name="hibernate.connection.SetBigStringTryClob" value="true"/>
        <property name="hibernate.hbm2ddl.auto" value="update"/>
        <property name="current_session_context_class" value="thread" />
        <property name="cache.provider_class" value="org.hibernate.cache.NoCacheProvider" />
    </properties>
</persistence-unit>   

出于测试目的,我添加了“hsqldb.lock_file=false”,但完全没有效果。一般来说,我不想禁用文件锁定...

谢谢!

【问题讨论】:

    标签: java jakarta-ee jpa hsqldb


    【解决方案1】:

    如果您需要从同一个 Web 应用程序中访问该数据库,最好:

    1. "in-process"模式下运行HSQLDB。
    2. 将数据库定义为 Tomcat 的 resource 并使用 JNDI 访问它。

    这将有助于完全摆脱 hsqldb 启动/停止的负担。

    【讨论】:

    • 你能给我更多关于那个解决方案的细节吗?我的 persistence.xml 会是什么样子?如果我定义了资源并且必须告诉实际的 HSQL 文件在哪里。我还有动态设置文件路径的问题...
    • 作为资源存储的 HSQLDB 数据库是只读的。见hsqldb.org/doc/1.8/src/org/hsqldb/jdbc/jdbcConnection.html
    【解决方案2】:

    你好这样解决了这个问题:

    @Override
    public void destroy() {
        controller.shutdown();
        PersistenceUtility.getInstance().closeAllEntityManagers();
    
        try {
            EntityManager em = PersistenceUtility.getInstance().createEntityManager();
            em.getTransaction().begin();
            Query shutdownQuery = em.createNativeQuery("SHUTDOWN");
            shutdownQuery.executeUpdate();
            em.getTransaction().commit();
        } catch (Throwable t) {
            Environment.LOGGER.debug("Database connection closed");
        }
    
        server.signalCloseAllServerConnections();
        server.shutdown();
        super.destroy();
    }
    

    我剩下的唯一问题是本机查询SHUTDOWN 可以解决问题,但也会触发相应EntityManager 引发的异常。我的理论是在 EntityManager 关闭其连接之前数据库已关闭并停止...

    如果我打印捕获的Throwable t 的堆栈跟踪,我会得到:

    javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not execute native bulk manipulation query
        at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:637)
        at org.hibernate.ejb.QueryImpl.executeUpdate(QueryImpl.java:58)
        at com.convista.fst.manager.ConfigurationServlet.destroy(ConfigurationServlet.java:115)
        at org.apache.catalina.core.StandardWrapper.unload(StandardWrapper.java:1417)
        at org.apache.catalina.core.StandardWrapper.stopInternal(StandardWrapper.java:1764)
        at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:230)
        at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5449)
        at java.lang.Thread.run(Thread.java:722)
    Caused by: org.hibernate.exception.JDBCConnectionException: could not execute native bulk manipulation query
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:74)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
        at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:174)
        at org.hibernate.impl.SessionImpl.executeNativeUpdate(SessionImpl.java:1163)
        at org.hibernate.impl.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:334)
        at org.hibernate.ejb.QueryImpl.executeUpdate(QueryImpl.java:49)
        ... 6 more
    Caused by: java.sql.SQLTransientConnectionException: connection exception: connection failure: java.net.SocketException: Software caused connection abort: socket write error
        at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
        at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
        at org.hsqldb.jdbc.JDBCPreparedStatement.close(Unknown Source)
        at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534)
        at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:269)
        at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:169)
        ... 9 more
    Caused by: org.hsqldb.HsqlException: connection exception: connection failure: java.net.SocketException: Software caused connection abort: socket write error
        at org.hsqldb.error.Error.error(Unknown Source)
        at org.hsqldb.error.Error.error(Unknown Source)
        at org.hsqldb.ClientConnection.execute(Unknown Source)
        ... 13 more
    

    你知道是什么导致了这个异常吗?

    【讨论】:

      【解决方案3】:

      从 HSQLDB 2.4.1 开始,关闭 HSQL 服务器的正确方法似乎是通过 org.hsqldb.server.Server 类的 shutdownCatalogs 或 shutdownWithCatalogs 方法。

      在你的情况下,这将是:

      server.shutdownCatalogs(org.hsqldb.Database.CLOSEMODE_NORMAL);
      

      一个明显的问题是,当最后一个数据库关闭时,stop() 最终被调用,然后 shutdown() 也被调用,这导致一些冗余的内部调用,但它似乎没有害处。

      【讨论】:

        猜你喜欢
        • 2021-11-20
        • 2018-12-19
        • 1970-01-01
        • 1970-01-01
        • 2013-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多