【问题标题】:Slick: How to neatly close resources and chain actionsSlick:如何巧妙地关闭资源和链式操作
【发布时间】:2018-04-27 10:15:13
【问题描述】:

我今天写了一个小程序。有用。这是代码

package com.abhi

import slick.driver.MySQLDriver.api._
import slick.jdbc.meta.MTable
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Success, Failure}

object MySlickApp extends App {
   val db = Database.forConfig("essential-slick ")
   val messages = TableQuery[MessageTable]

   val tableExists = MTable.getTables map { tables =>
      tables.exists(_.name.name == messages.baseTableRow.tableName)
   }

   val dropAction = messages.schema.drop
   val createAction = messages.schema.create

   val freshMessages = Seq(
      Message("Dave", "Hello HAL. Do you read me? HAL?"),
      Message("HAL", "Affirmtive, Dave. I read you."),
      Message("Dave", "Open the pod doors, HAL."),
      Message("HAL", "I'm Sorry. Dave. I'm afraid, I cannot do that.")
   )

   val insertAction = messages ++= freshMessages

   val f5 = for {
      f1 <- db.run(tableExists)
      f2 <- db.run(dropAction) if f1 == true
      f3 <- db.run(createAction)
      f4 <- db.run(insertAction)
   } yield (f1, f2, f3, f4)

   f5.onComplete{
      case Success(s) => println("table initialized successfully "); db.close
      case Failure(f) => println(f.getMessage); db.close
   }
   scala.io.StdIn.readLine()
}

final case class Message (sender: String, content: String, id: Long = 0L)

final case class MessageTable(tag: Tag) extends Table[Message](tag, "Message") {
   def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
   def sender = column[String]("sender")
   def content = column[String]("content")
   def * = (sender, content, id) <> (Message.tupled, Message.unapply)
}

这个程序有两点我不喜欢

  1. 我必须在 for comprehension 的每一行中指定 db.run。我试图将我的所有操作都放在 Seq 中,然后将 DBIO.seq 提供给 db.run,但它运行的是异步而不是顺序。

  2. 我必须在“成功”和“失败”两种情况下都调用 db.close。我想知道是否有一种方法可以在一个地方关闭资源而不会重复。

【问题讨论】:

  • 对于第二个子句,您可以将 andThen()onComplete() 组合在一个地方关闭数据库,而不会重复。你能在第一个子句的 db 中显示你的结果吗?

标签: scala slick slick-3.0


【解决方案1】:

使用最新的 slick 3.2 1.您可以通过将 DBIOActions 链接在一起而不是期货来以这种方式运行它作为单个数据库运行。这样做还提供了将其作为事务运行的额外好处:

val f = for {
     r1 <- tableExists
     r2 <- {
       if(r1){
             dropAction
          }else{ 
             DBIO.successful()
          }
        }
      r3 <- createAction
      r4 <- insertAction
   } yield (f)
db.run(f).transactionally
  1. 调用db.close:确实没有必要调用db close。这不会关闭连接。这样做会关闭整个数据库设置/连接池等)。没有手动关闭连接的机制,因为 slick 已经在 db.run 调用中为您处理了这个问题。 由于这是一个“运行一次”程序,因此无论哪种方式都无关紧要。如果这是作为 Web 服务类型的程序运行的,那么对该服务的任何后续请求都将永远无法再次连接到数据库!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多