2016-08-29 52 views
4

我目前正在學習Play2,Scala和Slick 3.1,並且很喜歡使用insertOrUpdate的語法,並想知道是否有人可以幫助我。如何使用Slick的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和油滑所以道歉,如果我失去了一些東西真的很明顯。

回答

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的信息。

1

您不能返回整份報告,第一回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功能相應

+0

此非常感謝 - 然而insertorupdate是一個漂亮的內置功能,所以不是我可以這樣更新。我希望使用它,因爲它要麼更新記錄,要麼插入,如果它不存在 - 但我找不到任何方式返回整個行使用它,甚至會話ID。 – jnhamilton

+0

@jnhamilton你可以在這種情況下使用'save_report'而不是'insertOrUpdate'。 – pamu

+0

我看到了謝謝,我明天會試試這個,並更新票證 – jnhamilton

0

您可以返回整行,但它是一個選項,正如文檔所述,它在更新時將爲空,並且將表示插入行上的插入行的Some(...)。

所以正確的代碼將

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