SLICK 3.0 - multiple queries depending on one another - db.run(action)

后端 未结 1 2123
失恋的感觉
失恋的感觉 2021-02-20 05:45

I am new to Slick 3 and so far I have understood that db.run are asynchronous call. the .map or .flatMap is run once the Future is returned.

The problem in my code below

1条回答
  •  星月不相逢
    2021-02-20 06:16

    The problem in my code below is that all the sub queries do not work (nested db.run)

    I suspect you're ending up with nested Future[R] results. I've not investigated that though. Because...

    Conceptually speaking, what am I not getting?

    The way I'd tackle this is to look at combining DBIO[R]. That might be the concept that helps.

    What you're doing is trying to run each action (query, insert...) individually. Instead, combine the individual actions into a single action and run that.

    I'd re-write the main logic as this:

      val action: DBIO[Int] = for {
        existingEnterprise <- enterpriseQS.headOption
        rowsAffected       <- existingEnterprise match {
          case Some(n) => salaries += new SalaryRow(0, n.id, salaryItem.worker)
          case None    => createNewEnterprise(salaryItem)
        }
      } yield rowsAffected
    

    For the None case I'd create a helper method:

      def createNewEnterprise(salaryItem: SalaryItem): DBIO[Int] = for {
        eId          <- (enterprises returning enterprises.map(_.id)) += EnterpriseRow(0, salaryItem.enterpriseName)
        rowsAffected <- salaries += new SalaryRow(0, eId, salaryItem.worker)
      } yield rowsAffected
    

    Finally, we can run that:

      val future: Future[Int] = db.run(action)
      // or db.run(action.transactionally)    
    
      val result = Await.result(future, 2 seconds)
    
      println(s"Result of action is: $result")
    

    The second half of a blog post I've written talks more about this.

    The code I've used is: https://github.com/d6y/so-31471590

    0 讨论(0)
提交回复
热议问题