在recommended transaction setup for Squeryl之后,在我的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
))
第一次启动工作正常。我可以通过H2的网络界面连接,如果我使用我的应用程序,它会适当地更新数据库。但是,如果我在不重新启动JVM的情况下重新启动jetty,我会得到:
java.sql.SQLException: No suitable driver found for jdbc:h2:lift_proto.db;DB_CLOSE_DELAY=-1
如果我将“DB_CLOSE_DELAY = -1”替换为“AUTO_SERVER = TRUE”,或者将其完全删除,则会产生相同的结果。
按照Squeryl列表中的建议,我尝试了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:
transaction { /* Do nothing */ }
然后再次抛出异常(我假设因为连接是懒惰的)。所以我将数据库初始化代码移到了自己的文件中,远离Lift:
SessionFactory.concreteFactory = Some(()=>
Session.create(
java.sql.DriverManager.getConnection("jdbc:h2:mem:test", "sa", ""),
new H2Adapter
))
transaction {}
结果没有变化。我究竟做错了什么?我在Squeryl文档中找不到任何需要显式关闭连接或会话的提及,这是我第一次使用JDBC。
我发现提到同一问题here on the Lift google group,但没有解决方案。
感谢您的帮助。
答案 0 :(得分:1)
当你说你正在重启Jetty时,我认为你真正在做的是在Jetty中重新加载你的webapp。当您的应用重新加载时,h2数据库或C3P0都不会自动关闭,这解释了当Lift尝试再次初始化它们时收到的错误。当您没有创建事务块时,您不会看到错误,因为在检索到第一个数据库连接时,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数据库。