如何将Scala Squeryl ORM与Play 2.0框架集成?

11

我正在尝试在Play 2.0框架中使用Squeryl ORB,但在初始化期间调用DB.getConnection()时,我收到以下错误:

BadPath:路径参数:无效路径' - 无法找到defaultdb数据源':在路径表达式中不允许使用标记:' - '(如果你真的想在此处使用它,可以将此标记加双引号)

数据库配置如下(conf/application.conf):

db.default.url="jdbc:postgresql://localhost/mydb?user=postgres&password=postgres"
db.default.driver=org.postgresql.Driver
db.default.jndiName=defaultdb

并且初始化:

object Global extends GlobalSettings {
  override def onStart(app: Application) {

    SessionFactory.externalTransactionManagementAdapter = Some(() => 
        Some(new Session(
          DB.getConnection("defaultdb", true),
          new PostgreSqlAdapter)))
    ...

这是正确的方式吗?使用db.default.jndiName配置值作为DB.getConnection()方法的参数值是否正确?

还是应该像这样实现:

  SessionFactory.concreteFactory = Some(() =>
    Session.create(
      java.sql.DriverManager.getConnection("jdbc:postgresql://..."),
      new PostgreSqlAdapter))

这个方法可行,但是我无法在模板中使用Squeryl查询对象进行迭代,我本希望通过 externalTransactionManagementAdapter 实现这一点。

更新:

我改正为以下代码:DB.getConnection("default", true) 并移除了db.default.jndiName 配置。 这样我可以获取并使用连接,但第二次调用 getConnection() 时,会抛出 SQLException: Timed out waiting for a free available connection.

更新2:

我没有成功使用externalTransactionManagementAdapter,但concreteFactory效果很好——如下所述。


你能否更详细地描述一下你想要实现什么?我对Play或“迭代模板”并不是很熟悉。externalTransactionManagementAdapter用于处理SQL事务将在Squeryl之外进行的情况(而不是使用transaction{} / inTransaction{}块)。从你的问题中我无法确定它是否符合你的需求。 - Dave Whittaker
如果我理解"play"正确的话,它应该能够为我处理SQL事务。在这种情况下,我应该能够在事务块之外迭代squeryl查询,例如在渲染play模板中的html时,对吧?描述的错误可能更多是play问题,而不是squeryl的问题。 - Roar Skullestad
1个回答

8

接下来是适合我的工作:

import play.db.DB 
import play.api.Application 
import play.api.GlobalSettings 
import org.squeryl._ 
import org.squeryl.adapters._ 

....

object Global extends GlobalSettings
{

override def onStart(app:Application):Unit =
{
 SessionFactory.concreteFactory = Some(
      () => Session.create(DB.getDataSource().getConnection(),
                           dbAdapter)
 );
}

override def onStop(app:Application):Unit =
{
}

val dbAdapter = new PostgreSqlAdapter();

}

谢谢!我已经改用这段代码了,但是我仍然像上面更新的那样收到“SQLException: Timed out...”的错误。你是否在“transaction”块中使用连接?你能否给出一个简单的选择示例以及它所使用的上下文? - Roar Skullestad
当所有连接都被获取且没有被释放时,BoneCP 会抛出此异常。原因可能是应用程序错误(根本没有关闭JDBC连接;使用事务而不是inTransaction并嵌套一个块超过池大小,在内部进行连接抓取的循环等)。 - rssh
2
因此,在日志中启用跟踪[最小 - application.log =应用程序.conf中的TRACE],更详细地--特别为“com.jolbox.bonecp”记录器启用跟踪,并在日志中查找“Check in connection”和“Check out connection”消息。 - rssh
每个HTTP请求(执行单个db-select)都会检查17个连接,但只有一个返回。问题出在我的externalTransactionManagementAdapter的使用上 - 以及当更改SessionFactory时需要手动重新启动play。因此,在使用concreteFactory时它确实可以工作,但是当在视图中使用squeryl查询时,需要在视图调用周围添加transaction块。我曾希望通过使用externalTransactionManagementAdapter来让play为我管理事务,但我想我仍然需要告诉squeryl如何“返回”连接... - Roar Skullestad
2
我个人使用concreteFactory,我建议不要在Play中使用externalTransactionManagementAdapter,因为它是为那些为您管理提交的框架而设计的(通常是按照每个Web请求模式,如Lift)。设置concreteFactory意味着您需要明确声明transaction {}或inTransaction {}。个人而言,我更喜欢显式事务。 - Max L.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接