使用分支链接DBIOAction,一个分支不执行任何操作

时间:2017-11-05 21:49:38

标签: database scala h2 slick slick-3.0

来自How to get max(id) of table = Rep[Option[Long]] for subsequent insert, without calling db.run in between

我的代码还有另一个问题:

def add(languageCode: String,
  typeId: Long,
  properties: Seq[Property]): Unit = {
    val dbAction = (
        for{
            nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
            language <- (languages.all filter (_.code === languageCode)).result.head
            _ <- DBIO.seq(properties.map
            {
            property =>
                val id = property.id
                val name = property.key
                val value = property.value
                if(id == 0) {
                  val currentPropId: FixedSqlAction[Option[Long], h2Profile.api.NoStream, Effect.Read] = this.properties.all.map(_.id).max.result
                  val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(language.id.get, currentPropId + 1, name)
                  nodeProperties.all += NodeProperty(nodeId, 2, value)
                } else {
                  nodeProperties.all += NodeProperty(nodeId, id, value)
                }
            }: _*)
        } yield()).transactionally

        db.run(dbAction)
}

1) 基本思想是,如果对于id为0的每个属性,有两个要调用的插入。一个实际在某个表中创建新属性,另一个也将该属性的值添加到另一个表中。

那是在:

if(id == 0) {
    val currentPropId: Rep[Option[Long]] = this.properties.all.map(_.id).max
    // FIXME get rid of hardcoded languageId
    val DUMMY_LANGUAGE_ID = 1
    val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(DUMMY_LANGUAGE_ID, currentPropId + 1, name)
    nodeProperties.all += NodeProperty(nodeId, 2, value)
}

一部分。

现在,如果,则只需要将属性的值插入到正确的表中,这就是else部分的用途。

我面临的问题是,id == 0没有插入任何内容。

我也尝试过这样:

if(id == 0) {
    val nextPropId: Rep[Option[Long]] = this.properties.all.map(_.id).max
    // FIXME get rid of hardcoded languageId
    val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(1, 10, name)
    val nodeProperty = nodeProperties.all += NodeProperty(nodeId, 2, value)
    propertyId andThen nodeProperty
}

但无济于事。

else部分工作正常。我在这里缺少什么?

编辑:

因为我被问到了。

val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(language.id.get, 10, name)
val nodeProperty = nodeProperties.all += NodeProperty(nodeId, 2, value)

log.info(s"Statements: ${propertyId.statements}")
log.info(s"${nodeProperty.statements}")

给了我:

  

语句:向量(插入“属性”)   (“language_id”,“property_id”,“name”)值(?,?,?))Vector(插入   到“node_property”(“node_id”,“property_id”,“value”)值   (?,?,?))

看起来很好。

我很想记录dbAction本身的内容,但因为它是DBIOAction我没有找到以有意义的方式这样做的方法。

如果我将记录设置为跟踪,我会得到:

22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - ------------------- Phase: Time ---------
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark -       assignUniqueSymbols:    0.456428 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark -                inferTypes:    0.089135 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark -            insertCompiler:    0.292443 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark -                   codeGen:    0.534494 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark -                     TOTAL:    1.372500 ms
22:18:16:016 - [debug] s.b.B.action - #5: Rollback

不知道为什么最后一行显示Rollback之前的一切(相当多)对我来说似乎没问题。

EDIT2

看起来我终于拥有了

val dbAction = for {
      nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
      languageId <- (languages.all filter (_.code === languageCode)).map(_.id).result.head
      _ <- DBIO.seq(properties.values.map
      {
        property =>
          val id = property.id
          val name = property.key
          val value = property.value

          if(id == 0) {
            for {
              currentPropId <- this.properties.all.map(_.id).max.result
              propertyId <- (this.properties.all returning this.properties.all.map(_.id)) += Property(languageId, currentPropId.get + 1, name)
              _ <- this.nodeProperties.all += NodeProperty(nodeId, propertyId, value)
            } yield ()
          } else {
            this.nodeProperties.all += NodeProperty(nodeId, id, value)
          }
      }: _*)
    } yield ()

1 个答案:

答案 0 :(得分:1)

看起来最终的答案是重组一下:

 val dbAction = for {
      nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
      languageId <- (languages.all filter (_.code === languageCode)).map(_.id).result.head
      _ <- DBIO.seq(properties.values.map
      {
        property =>
          val id = property.id
          val name = property.key
          val value = property.value

          if(id == 0) {
            for {
              currentPropId <- this.properties.all.map(_.id).max.result
              propertyId <- (this.properties.all returning this.properties.all.map(_.id)) += Property(languageId, currentPropId.get + 1, name)
              _ <- this.nodeProperties.all += NodeProperty(nodeId, propertyId, value)
            } yield ()
          } else {
            this.nodeProperties.all += NodeProperty(nodeId, id, value)
          }
      }: _*)
    } yield ()

我很想看到其他解决方案,但这是我在另一个长期试错会后发现的解决方案。我仍然不确定为什么我无法使用andThen方法。

我想知道transactionally如果内部for理解中发生了什么,会发生什么。我想根据我对文档的解释 - http://slick.lightbend.com/doc/3.2.1/dbio.html#transactions-and-pinned-sessions

,它不会起作用
  

嵌套的事务性操作只需在现有事务中执行,无需额外的保存点。