Scala Squeryl 0.9.5(使用Lift 2.4)未释放数据库连接/池

Scala Squeryl 0.9.5(使用Lift 2.4)未释放数据库连接/池,scala,jdbc,sbt,h2,squeryl,Scala,Jdbc,Sbt,H2,Squeryl,在my Boot.scala中的以下命令: import net.liftweb.squerylrecord.SquerylRecord import org.squeryl.Session import org.squeryl.adapters.H2Adapter SquerylRecord.initWithSquerylSession(Session.create( DriverManager.getConnection("jdbc:h2:lift_proto.db;DB_CLOSE_

在my Boot.scala中的以下命令:

import net.liftweb.squerylrecord.SquerylRecord
import org.squeryl.Session
import org.squeryl.adapters.H2Adapter

SquerylRecord.initWithSquerylSession(Session.create(
  DriverManager.getConnection("jdbc:h2:lift_proto.db;DB_CLOSE_DELAY=-1", "sa", ""),
  new H2Adapter
))
transaction { /* Do nothing */ }
第一次启动运行良好。我可以通过H2的web界面进行连接,如果我使用我的应用程序,它会相应地更新数据库。但是,如果我在不重新启动JVM的情况下重新启动jetty,我会得到:

java.sql.SQLException: No suitable driver found for jdbc:h2:lift_proto.db;DB_CLOSE_DELAY=-1
如果我将“DB\u CLOSE\u DELAY=-1”替换为“AUTO\u SERVER=TRUE”,或者将其完全删除,则会得到相同的结果

按照Squiryl列表上的建议,我尝试了C3P0:

import com.mchange.v2.c3p0.ComboPooledDataSource

val cpds = new ComboPooledDataSource 
cpds.setDriverClass("org.h2.Driver") 
cpds.setJdbcUrl("jdbc:h2:lift_proto") 
cpds.setUser("sa") 
cpds.setPassword("")
org.squeryl.SessionFactory.concreteFactory =
  Some(() => Session.create( 
    cpds.getConnection, new H2Adapter())
  )
这会产生类似的行为:

WARNING: A C3P0Registry mbean is already registered. This probably means that an application using c3p0 was undeployed, but not all PooledDataSources were closed prior to undeployment. This may lead to resource leaks over time. Please take care to close all PooledDataSources.
为了确保这不是我所做的任何事情造成的,我启动并停止了服务器,而没有调用事务{}块。没有抛出异常。然后,我将以下内容添加到我的Boot.scala中:

import net.liftweb.squerylrecord.SquerylRecord
import org.squeryl.Session
import org.squeryl.adapters.H2Adapter

SquerylRecord.initWithSquerylSession(Session.create(
  DriverManager.getConnection("jdbc:h2:lift_proto.db;DB_CLOSE_DELAY=-1", "sa", ""),
  new H2Adapter
))
transaction { /* Do nothing */ }
然后再次抛出异常(我假设是因为连接是惰性的)。因此,我将db初始化代码从Lift移到了它自己的文件中:

SessionFactory.concreteFactory = Some(()=>
  Session.create(
  java.sql.DriverManager.getConnection("jdbc:h2:mem:test", "sa", ""),
  new H2Adapter
))
transaction {}
结果没有变化。我做错了什么?我在Squeryl文档中找不到任何需要显式关闭连接或会话的内容,这是我第一次使用JDBC

我发现有人提到同样的问题,但没有解决


谢谢您的帮助。

当您说要重新启动Jetty时,我认为您实际上是在Jetty中重新加载您的Web应用程序。当你的应用程序重新加载时,h2数据库或C3P0都不会自动关闭,这解释了当Lift再次尝试初始化它们时你收到的错误。如果不创建事务块,则不会看到错误,因为在检索第一个DB连接时,h2和C3P0都已初始化

我自己倾向于使用BoneCP作为连接池。您可以将池连接的最小数量配置为>1,这将阻止h2关闭,而不需要DB_CLOSE_DELAY=-1。然后您可以使用:

    LiftRules.unloadHooks append { () =>
      yourPool.close() //should destroy the pool and it's associated threads
    }

这将在Lift关闭时关闭所有连接,这也将正确关闭h2数据库。

这不是问题的解决方案,但请注意,数据库URL
jdbc:h2:Lift_proto
将在当前工作目录中创建数据库文件,这在很多情况下都有点问题,因为当前工作目录是启动应用程序的地方。最好使用绝对路径,例如
jdbc:h2:/data/db/lift\u proto