如何使用Slick的insertOrUpdate返回完整行

问题描述 投票:6回答:3

我目前正在学习Play2,Scala和Slick 3.1,并且我非常坚持使用insertOrUpdate的语法,并想知道是否有人可以帮助我。

我想要做的是在使用insertOrUpdate(包括auto inc主键)时返回完整行,但我只是设法返回更新/插入的行数。

这是我的表定义:

package models

final case class Report(session_id: Option[Long], session_name: String, tester_name: String, date: String, jira_ref: String,
                  duration: String, environment: String, notes: Option[String])

trait ReportDBTableDefinitions {

  import slick.driver.PostgresDriver.api._

  class Reports(tag: Tag) extends Table[Report](tag, "REPORTS") {

    def session_id = column[Long]("SESSION_ID", O.PrimaryKey, O.AutoInc)
    def session_name = column[String]("SESSION_NAME")
    def tester_name = column[String]("TESTER_NAME")
    def date = column[String]("DATE")
    def jira_ref = column[String]("JIRA_REF")
    def duration = column[String]("DURATION")
    def environment = column[String]("ENVIRONMENT")
    def notes = column[Option[String]]("NOTES")

    def * = (session_id.?, session_name, tester_name, date, jira_ref, duration, environment, notes) <> (Report.tupled, Report.unapply)
  }

  lazy val reportsTable = TableQuery[Reports]

}

这是我的DAO与insertOrUpdate相关的部分,它工作得很好,但只返回更新/插入行的数量:

package models

import com.google.inject.Inject
import play.api.db.slick.DatabaseConfigProvider
import scala.concurrent.Future

class ReportsDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends DAOSlick {

  import driver.api._

  def save_report(report: Report): Future[Int] = {
    dbConfig.db.run(reportsTable.insertOrUpdate(report).transactionally)
  }
}

我试过玩“返回”,但我无法获得我需要的语法并继续获得类型不匹配,例如以下不编译(因为它可能完全错误!)

 def save_report(report: Report): Future[Report] = {
    dbConfig.db.run(reportsTable.returning(reportsTable).insertOrUpdate(report))
  }

任何帮助表示赞赏 - 我是Scala和Slick的新手,如果我遗漏了一些非常明显的东西,请道歉。

scala slick-3.0 playframework-2.5
3个回答
3
投票

解决了 - 发布它可以帮助其他人尝试做类似的事情:

//will return the new session_id on insert, and None on update
  def save_report(report: Report): Future[Option[Long]] = {
    val insertQuery = (reportsTable returning reportsTable.map(_.session_id)).insertOrUpdate(report)
    dbConfig.db.run(insertQuery)
  }

运行良好 - insertOrUpdate不返回更新时看起来的任何内容,因此如果我需要在更新操作后获取更新的数据,我可以运行后续查询以使用会话ID获取信息。


2
投票

你不能返回整个报告,首先返回Id(returning(reportsTable.map(_.session_id))),然后获得整个对象

检查数据库中是否存在报告(如果存在)更新它,如果不继续将报告插入数据库。

注意使用Transactions以全部或全部方式执行上述操作

def getReportDBIO(id: Long): DBIO[Report] = reportsTable.filter(_.session_id === id).result.head

def save_report(report: Report): Future[Report] = {
  val query = reportsTable.filter(_.session_id === report.session_id)
  val existsAction = query.exists.result
  val insertOrUpdateAction = 
  (for { 
     exists <- existsAction
     result <- exists match {
        case true => 
        query.update(report).flatMap {_ => getReportDBIO(report.session_id)}.transactionally
        case false => {
           val insertAction = reportsTable.returning(reportsTable.map(_.session_id)) += report
           val finalAction = insertAction.flatMap( id => getReportDBIO(id)).transactionally //transactionally is important
            finalAction
        }
     }
  } yield result).transactionally

  dbConfig.db.run(insertOrUpdateAction)
}

相应地更新insertOrUpdate函数


1
投票

您可以返回完整行,但它是一个Option,正如文档所述,它在更新时将为空,并且将是表示插入上插入行的Some(...)。

所以正确的代码就是

    def save_report(report: Report): Future[Option[Report]] = {dbConfig.db.run(reportsTable.returning(reportsTable).insertOrUpdate(report))}
© www.soinside.com 2019 - 2024. All rights reserved.