关闭H2的正确方法是什么?

这与这篇文章有关 。
我认为我遇到H2问题意味着它没有正确关闭。
我怀疑这是因为当我关闭tomcat并且进程没有停止时我看到myDB.lock.db
我使用Tomcat的连接池,数据库的URL是:
url="jdbc:h2:file:/opt/myOrg/tomcat/webapps/MyApplication/db/myDatabase;SCHEMA=myschema"

来自doc close H2 :

通常,数据库在最后一次连接关闭时关闭….默认情况下,数据库在最后一个连接关闭时关闭。 但是,如果它从未关闭,则在虚拟机使用关闭挂钩正常退出时,数据库将关闭

我无法理解我是否做错了什么。
我应该通过命令强制关闭数据库吗? 这是关机钩子的意思吗?
我在这做错了什么?

注意:
我在Google中找不到如何正确关闭H2的示例(除了它在上次连接关闭时自动关闭的声明)。 我应该自己打电话给SHUTDOWN吗? 这是正确的方法吗?
我已经看到投票来结束这个问题了,但我正在调查的一个例子没有理由或联系

更新:
在Joonas Pulakka回答一些额外信息之后:

javacore我使用kill -3我看到线程:

“H2 Log Writer MYAPPLICATION”J9VMThread:0x08DC6F00,j9thread_t:0x08C9B790,java / lang / Thread:0xE7206CC8,状态:CW,prio = 5 3XMTHREADINFO1(本机线程ID:0xA32,原生优先级:0x5,本机策略:UNKNOWN)3XMTHREADINFO2
(本机堆栈地址范围从:0xE5E26000,到:0xE5E67000,大小:0x41000)3XMTHREADINFO3 Java callstack:
java / lang / Object.wait中的4XESTACKTRACE(本机方法)
4XESTACKTRACE at java / lang / Object.wait(Object.java:196(Compiled Code))4XESTACKTRACE at org / h2 / store / WriterThread.run(WriterThread.java:102)
java / lang / Thread.run中的4XESTACKTRACE(Thread.java:736)

3XMTHREADINFO“pool-8-thread-1”J9VMThread:0x087C0200,j9thread_t:0x0840566C,java / lang / Thread:0xE79BFC80,state:P,prio = 5
3XMTHREADINFO1(本机线程ID:0xE1A,本机优先级:0x5,本机策略:UNKNOWN)3XMTHREADINFO2
(本机堆栈地址范围从:0xE5F69000,到:0xE5FAA000,大小:0x41000)3XMTHREADINFO3 Java callstack:
太阳下​​的4XESTACKTRACE / misc / Unsafe.park(原生方法)
4XESTACKTRACE at java / util / concurrent / locks / LockSupport.park(LockSupport.java:184(Compiled Code))4XESTACKTRACE at java / util / concurrent / locks / AbstractQueuedSynchronizer $ ConditionObject.await(AbstractQueuedSynchronizer.java:1998(Compiled Code)) 4XESTACKTRACE at java / util / concurrent / LinkedBlockingQueue.take(LinkedBlockingQueue.java:413(Compiled Code))4XESTACKTRACE at java / util / concurrent / ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:958(Compiled Code))4XESTACKTRACE at java / util / concurrent / ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:918)4XESTACKTRACE at java / lang / Thread.run(Thread.java:736)

3XMTHREADINFO“H2 File Lock Watchdog opt / myOrg / tomcat / webapps / MyApplication / db / myDatabase.lock.db”J9VMThread:0x08DC6900,j9thread_t:0x08C9BA24,ja
va / lang /线程:0xE71E9018,状态:CW,prio = 9 3XMTHREADINFO1
(本机线程ID:0xA30,本机优先级:0x9,本机策略:UNKNOWN)
3XMTHREADINFO2(本机堆栈地址范围:0xE5DBA000,到:0xE5DFB000,大小:0x41000)3XMTHREADINFO3 Java callstack:java / lang / Thread.sleep(Native Method)的4XESTACKTRACE 4XESTACKTRACE
at java / lang / Thread.sleep(Thread.java:851(Compiled Code))
4xESTACKTRACE at org / h2 / store / FileLock.run(FileLock.java:490)4XESTACKTRACE
at java / lang / Thread.run(Thread.java:736)

3XMTHREADINFO“FileWatchdog”J9VMThread:0x087C0800,j9thread_t:0x08C9B4FC,java / lang / Thread:0xE715D878,状态:CW,prio = 5
3XMTHREADINFO1(本机线程ID:0xA2C,本机优先级:0x5,本机策略:UNKNOWN)3XMTHREADINFO2
(本机堆栈地址范围从:0xE5E67000,到:0xE5EA8000,大小:0x41000)3XMTHREADINFO3 Java callstack:
java / lang / Thread.sleep上的4XESTACKTRACE(本机方法)java / lang上的4XESTACKTRACE / Thread.sleep(Thread.java:851(编译代码))org / apache / log4j / helpers / FileWatchdog.run中的4XESTACKTRACE(FileWatchdog.java :104)

文档说明当虚拟机正常退出时,H2数据库连接将关闭。 这就是它的作用。 默认情况下,关闭挂钩已存在,您无需执行任何操作。 关闭钩子是一种完全有效的关闭资源的方法,只需要在退出时关闭。

如果关闭后仍有.lock.db文件,则虚拟机无法正常退出。 你写道, 这个过程并没有停止 。 你必须找到原因,因为这可能也阻止了H2关闭钩子的执行。

对于大型数据库,关闭可能需要一些时间。 请参阅调试器(例如VisualVM),在调用(Tomcat)关闭后,哪些线程保持活动状态。

有更多的可能性:设置文件权限,以便H2可以创建锁定文件,但不能删除它们。 如果操作系统阻止H2删除其锁定文件,那么H2就无法做到这一点。

您可以执行语句SHUTDOWN ,然后关闭连接。

SHUTDOWN命令将使H2立即释放与连接相关的所有资源。 例如,这将允许您在重新部署Web应用程序时删除嵌入式H2数据库。

通过查看DbStarter.contextDestroyed()的代码(感谢Allan5的回答 ),这里的代码将起作用:

 connection.createStatement().execute("SHUTDOWN"); 

所以Aaron Digulla的回答是正确的(即使不是完全“复制/可接受”)。

此外,如果您使用server = Server.createTcpServer("-tcpAllowOthers")启动了H2 TCP服务器,则只需使用server.stop()即可停止它。

不,关闭钩子只是一个在JVM终止时运行的线程,无论是从main()返回,调用System.exit(int)还是抛出exception。 只有JVM崩溃才能避免它。 请参见Runtime.addShutdownHook(Thread)。

不确定这是否与您的情况相关,但您是否尝试添加DBStarter侦听器?

http://www.h2database.com/html/tutorial.html ,请参阅“使用Servlet侦听器启动和停止数据库”部分。

该链接建议将以下内容添加到web.xml:

  org.h2.server.web.DbStarter  

请参阅此处的讨论(诚然从2008年开始,因此可能已过期) – 显然此修复程序适用于嵌入式和非嵌入式实例: http : //groups.google.com/group/h2-database/browse_thread/thread/eb609d58c96f4317

或者你如何使用连接? 您确定要正确清理连接吗?

之前我遇到过问题,在我的情况下,我使用了与JPA EntityManager的连接,我忘了在使用后关闭EntityManager实例,这导致了一些问题:

 @PersistenceUnit(unitName="myEm") private EntityManagerFactory emf; public void doStuff() { EntityManager em = emf.createEntityManager(); ... em.close(); // forgot this line }