2017-11-05 2 views
1

How to get max(id) of table = Rep[Option[Long]] for subsequent insert, without calling db.run in betweenチェーンDBIOAction、一方の分岐は、私は私のコードではまだ別の問題があり、何も

から来ないん:

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であれば、呼び出される挿入が2つあります。 1つは実際にそのテーブルの新しいプロパティを作成し、もう1つはそのプロパティの値を別のテーブルに追加するものです。中だ

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"、 "名")の値(、)に挿入します) "node_property" に を挿入します( "NODE_ID"、 "PROPERTY_ID"、 "値")だけで正常に見える (?、?、?))

値。

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() 
+0

私は間違っているかもしれませんが、 'id == 0'の場合は、' DBIO.seq'で終わる挿入アクションだけを返すと思います。しかし、それは何も挿入されていない理由を説明していません... – LiMuBei

+0

まあ、私はそれぞれのプロパティのために1つを追加しますが、それは 'と'それは 'andThen'(最新の試みで)とチェーンしているので、それは' else'と同じです – Lichtbringer

+0

Slickが生成しているステートメントを印刷しようとしましたか? –

答えて

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のアプローチを働かせることができなかったのかまだ分かりません。

そしてforの中に何かが起これば、transactionallyに何が起こるのだろうと思います。私はそれがドキュメントの私の解釈に従って動作しないと思う - http://slick.lightbend.com/doc/3.2.1/dbio.html#transactions-and-pinned-sessions

ネストされたトランザクションアクションは、単に追加のセーブポイントなしで既存のトランザクション内で実行されます。

関連する問題