2016-01-23 18 views
5

この質問は約滑らかな3.0または3.1である(私は約フレキシブル午前)スカラ+ 3:別のテーブルへつのクエリの結果を挿入

私はmapforなどで処理中間クエリを持っています私が望む結果を得るために。最後に、私は

val foo: DBIOAction[Seq[MySchema.Bar], NoStream, Effect.Read] 

は、今私はval bar: TableQuery[MySchema.Bar]を持っていると私はそれにしてFOOを挿入します。

fooがSeqの場合、私は単にbar ++= fooを実行できますが、そうではありません。

私が見つけた唯一の方法は、それを待って結果を具体化することです。この

val query = (bar ++= Await.result(db.run(foo), Duration.Inf)) 
明らか

query同様db.runでいくつかの時点で実行する必要があります。しかし、今では2つのDBランがあります。すべてを1回実行する方が良いのではないでしょうか?

これを行うより良い方法はありますか? 、

+0

'バー+ = foo':だから、あなたが書くことができ、単一のクエリにこのような何かをコンパイルする

?しかし、 '+ ='か '++ =' ...(?)のどちらに関係なく 'db.run'する必要があります。 – kornfridge

+0

私は++ =副作用がslick2 apiであり、slick3より機能的なので、明示的に 'db.run'を実行する必要があります。 – kornfridge

+0

はい++ =の結果は、実行する必要のあるクエリになりました。私はこの時点で問題を編集しました。しかし、私はこの作業のために2つのdb.run呼び出しを行う必要があります。 – masgo

答えて

4

DBIOActionmap/flatMap機能を持っているので、あなたはinsertActionがそのようなタイプDBIOAction[Int, NoStream, Effect.Write]か何かのものであろう

val insertAction = foo.flatMap(bar ++= _) 

のようなものを書くことができます(私は完全にIntと効果についてはよく分かりません) DB上でを使用してDBIOActionとして実行することができます。次に得られるものは、全体的なクエリと挿入結果の未来です。

+0

'flatMap'はトリックです。結局私は実行する必要があるDBIOActionが1つだけ残っています。私はこのトピックで別のことを実行しました:db.run()はいつ行うべきですか?以下は 'val foo = dbの例です。'person.result.map(_。map {p => tr(td(p.id))}))'このようにするか、 '.resultの後に' db.run'を終了することができます'。どちらの方法も私に同じ「未来」を与えますが、パフォーマンス面で違いはありますか? – masgo

+2

一般に、できるだけ 'DBIO 'レベルで作業したいと思っています。 'db.run'を呼び出すと、slickは自身の実行コンテキストを使って多くのクエリが必要になり、' Future'を返します。私は、もしあなたがそうするならば、パフォーマンスに潜在的な違いがあると思うのは、滑らかさがDBアクセスに関してスレッドの使用を最適化するからです。 –

1

質問には既に回答していましたが、私はここで別の解決策を探していましたので、これは他の人に役立つかもしれません。

@AldoはDBIOレベルでできるだけ作業したいと考えていますが、さらに進んで、Queryレベルでできるはずです。これは、次のような単一のSQL文でコンパイルされるためです。データベースに送信することができます。

たとえば、selectからの挿入はINSERT INTO table1 SELECT...にコンパイルする必要があります。 flatMapを使用して複数のDBIOSを使用する場合、これはSELECTにコンパイルされ、値がメモリに格納され、INSERTステートメントがコンパイルされ、文字列の値が補間され、この新しいクエリがデータベース。実際には、選択によって多くの結果が返され、最悪の場合にはメモリがなくなる可能性があります。

val bar: TableQuery[MySchema.Bar] 

val foo: Query[MySchema.Bar, Bar, Seq] 

val insert: DBIO[Int] = bar.forceInsertAll(foo) 
関連する問題