h2 离开锁定文件,即使只创建一个连接并立即断开连接

Posted

技术标签:

【中文标题】h2 离开锁定文件,即使只创建一个连接并立即断开连接【英文标题】:h2 leaving lock file even though only create one connection and immediately disconnect 【发布时间】:2013-10-07 15:22:07 【问题描述】:

我的应用程序正在使用带有 Hibernate 的内存 h2 数据库,我注意到即使在关闭应用程序之后,h2 锁定文件仍然存在。即使我启动应用程序,然后立即关闭应用程序,也会发生这种情况。

进一步调查显示,当我第一次启动应用程序时,我进行了测试连接以检查数据库是否正常,如下所示(如果我无法连接则退出应用程序)

try

  Session session = HibernateUtil.getSession();
  Transaction t = session.getTransaction();
  t.setTimeout(10);
  session.beginTransaction();
  t.commit();
  HibernateUtil.closeSession(session);

catch (Exception ex)

  MainWindow.logger.log(Level.SEVERE, "Problem accessing database needs recreating:" + ex.getMessage(), ex);
  System.exit(0);

删除此代码解决了锁定文件的问题,它现在消失了。但是我不明白为什么在我关闭会话时它仍然没有消失。而且问题并没有消失,因为如果我在应用程序中做任何实际工作,那么我又会遇到锁定文件被遗忘的问题。

HibernateUtil 方法是

public static Session getSession()
    
        if (factory == null)
        
            Configuration config =
                    HibernateUtil.getInitializedConfiguration();
            factory = config.buildSessionFactory();
        
        Session hibernateSession =
                factory.openSession();
        return hibernateSession;
    

 public static void closeSession(Session session)
    
        if(session!=null)
        
            session.close();
        
    

 public static Configuration getInitializedConfiguration()
    
        Configuration config = new Configuration();

        config.setProperty(Environment.DRIVER,"org.h2.Driver");
        config.setProperty(Environment.URL,"jdbc:h2:"+Db.DBFOLDER+"/"+Db.DBNAME+";FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;CACHE_SIZE=50000");
        config.setProperty(Environment.DIALECT,"org.hibernate.dialect.H2Dialect");
        org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider");
        config.setProperty("hibernate.connection.username","jaikoz");
        config.setProperty("hibernate.connection.password","jaikoz");
        config.setProperty("hibernate.c3p0.numHelperThreads","10");
        config.setProperty("hibernate.c3p0.min_size","20");
        config.setProperty("hibernate.c3p0.max_size","100");
        config.setProperty("hibernate.c3p0.timeout","300");
        config.setProperty("hibernate.c3p0.maxStatementsPerConnection","50");
        config.setProperty("hibernate.c3p0.idle_test_period","3000");
        config.setProperty("hibernate.c3p0.acquireRetryAttempts","10");
        config.setProperty("hibernate.show_sql","false");
        addEntitiesToConfig(config);
        return config;
    

我的 url 连接的形式是

jdbc:h2:Database/Database.h2.db;FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;CACHE_SIZE=50000

我试着改成

jdbc:h2:Database/Database.h2.db;FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=TRUE;CACHE_SIZE=50000

但是没有效果

这对我来说是一个真正的问题的原因是我有一个用户可以使用的 recreateDatabase() 命令,这会在重新创建数据库文件之前物理删除它们,但是如果文件当然不能被删除仍在使用中,因为锁定文件的存在证明了它们。所以 recreateDatabase() 命令不起作用

【问题讨论】:

【参考方案1】:

您正在使用连接池。关闭连接并不会真正关闭它,它只会将连接返回到池中。

这意味着第一步是阅读C3P0ConnectionProvider 的文档以了解它如何与c3p0 对话。您需要访问ComboPooledDataSource,以便您可以致电reset()。将 min_size 设置为 0 也可能会有所帮助。

也就是说,除非您完全控制所有线程,否则这是非常危险的。如果您不这样做,那么其他一些线程可能想要访问数据库,就像您终止所有连接一样。因此,如果这是一个 Web 应用程序,您需要安装一个过滤器,只要您重置数据库,它就会拒绝所有请求。

另外请注意,您没有使用内存数据库;您正在使用基于文件的嵌入式数据库。要创建内存数据库,请使用jdbc:h2:mem:

【讨论】:

谢谢,我想我已经解决了我需要使用 factory.close() 关闭休眠会话工厂,是的,我使用的是嵌入式数据库。【参考方案2】:

大家好,这是来自本地互联网的错误 如果你添加你的数据库端口号,以 connectionurl 结尾 它会变好的 例如 jdbc:mysql://127.0.0.1:3307/hibernateExamples

【讨论】:

以上是关于h2 离开锁定文件,即使只创建一个连接并立即断开连接的主要内容,如果未能解决你的问题,请参考以下文章

连接后立即断开Websocket

如何断开 Glassfish 上的所有 JDBC 连接并解锁 H2 数据库?

多台电脑使用H2文件模式可以吗

Jasper Studio 锁定 H2 嵌入式数据库?

H2 功能特点

H2 功能特点