【问题标题】:Keeping database session open保持数据库会话打开
【发布时间】:2013-06-04 18:37:23
【问题描述】:

我正在尝试利用 TypeSafe 的 slick 库与 MySQL 服务器进行交互。所有入门/教程示例都使用withSession{},其中框架将自动创建会话,在{} 中执行查询,然后在块的末尾终止会话。

我的程序很健谈,我想在脚本的整个执行过程中保持持久连接。到目前为止,我已将这段代码拼凑在一起,以显式创建和关闭会话。

val db = Database.forURL("jdbc:mysql://localhost/sandbox", user = "root", password="***", driver = "com.mysql.jdbc.Driver")
val s = db.createSession()
...
s.close()

我可以在其中执行查询。但是,当我尝试执行命令时,例如

(Q.u + "插入TEST (name) values('"+name+"')").execute

它崩溃是因为它找不到隐式会话。我不完全理解syntax of the execute definition in the documentation,但似乎可能有一个可选参数来传递显式会话。我尝试过使用 .execute(s),但会发出警告,表明 (s) 在纯表达式中没有做任何事情。

我如何明确指定一个预先存在的会话来运行查询?

附加:JAB解决方案的试用代码

class ActorMinion(name: String) extends Actor
{
    Database.forURL("jdbc:mysql://localhost/sandbox", user = "root", password="****", driver = "com.mysql.jdbc.Driver") withSession
    {
        def receive =
        {
            case Execute =>
            {
                (Q.u + "insert into TEST (name) values('"+name+"')").execute

                sender ! DoneExecuting(name,output,err.toString)
            }
        }
    }
}

返回编译错误

[错误] /home/ubuntu/helloworld/src/main/scala/hw.scala:41: 缺少扩展函数的参数类型

[错误] 匿名函数的参数类型必须是完全已知的。 (SLS 8.5)

[错误] 预期类型为:?

[错误] {

[错误] ^

[error] 发现一个错误

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    我能够从 this answer 得到我需要的东西

    //imports at top of file
    //import Database.threadLocalSession <--this should be commented/removed
    import scala.slick.session.Session // <-- this should be added
    ......
    //These two lines in actor constructor
    val db = Database.forURL("jdbc:mysql://localhost/sandbox", user = "root", password="****", driver = "com.mysql.jdbc.Driver")
    implicit var session: Session = db.createSession()
    ......
    session.close() //This line in actor destructor
    

    【讨论】:

      【解决方案2】:

      只需将脚本的相关部分附在withSession{} 中即可。请注意,如果您将会话保持打开一段时间/正在执行大量数据库操作查询,您还应该考虑利用事务。

      如果数据有潜在的外部来源,你真的应该使用准备好的语句进行插入。

      【讨论】:

      • 这似乎不适用于我的实施。我有一个演员接收我想要记录在数据库中的消息。消息通过 receive() 接口异步接收。我尝试将 withSession{} 包装在 receive() 定义周围,但 scala 不喜欢我在匿名函数中进行定义。
      • 另外,是的,在我可以使用基本查询为我的会话设置获得一个有效的 PoC 之后,我打算接下来处理事务/准备好的语句。 :)
      • Scala 不喜欢什么?诚然,我在上下文管理器中使用并发的工作不多,但我不明白为什么匿名函数内的定义与命名函数内的定义有任何不同。也许还有其他问题?
      • 我发布了我用来测试您建议的代码,以及它吐回的错误。我很可能错误地实现了它,因为我对 scala 还是很陌生。这也可能是更正确的方法,而我发布的内容更像是一种黑客攻击而不是正确的形式。至于返回的错误,我猜receive() 方法应该覆盖扩展Actor 类中继承的receive()。通过在 withSession 块内,我猜这不会正确覆盖。
      • 我认为问题更多在于您将 receive() 包裹在块中,而不是类本身及其任何用途(我自己对 Scala 还很陌生,但尝试使用类中的持久上下文管理器,而不是在管理器中拥有类和它的任何实例似乎不正确,尽管这可能只是由于我的 Python 背景)。尝试在对withSession 的调用中包装整个类定义,以及类的任何实例和这些实例的使用。如果这仍然给出错误,那么问题将是由于 Scala 类型推断的限制。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-10
      • 2023-03-22
      相关资源
      最近更新 更多