【问题标题】:How to return full row using Slick's insertOrUpdate如何使用 Slick 的 insertOrUpdate 返回整行
【发布时间】:2017-01-05 18:00:02
【问题描述】:

我目前正在学习 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


    【解决方案1】:

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

    //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】:

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

      所以正确的代码应该是

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

      【讨论】:

        【解决方案3】:

        不能返回整个Report,先返回Id(returning(reportsTable.map(_.session_id)))再获取整个对象

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

        请注意使用事务以全部或不进行上述操作

        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 函数

        【讨论】:

        • 非常感谢 - 但是 insertorupdate 是一个 Slick 内置函数,所以我无法更新。我希望使用它,因为它要么更新记录,要么在不存在时插入 - 但我找不到任何使用它返回整行的方法,甚至是会话 ID。
        • @jnhamilton 在这种情况下,您可以使用 save_report 而不是 insertOrUpdate。
        • 啊,我明白了,谢谢,我明天试试这个并更新票
        • 试过了,谢谢 - 当您尝试更新而不是更新现有记录时,它实际上会插入一条新记录,但它给了我一些尝试的想法:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-17
        • 2015-07-24
        • 1970-01-01
        相关资源
        最近更新 更多