Scala + Slick 3:将一个查询的结果插入另一个表中

时间:2016-01-23 23:37:36

标签: scala slick slick-3.0

这个问题是关于光滑的3.0或3.1(我对此很灵活)

我有一个中间查询,我使用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来运行memory。但现在我有两个DB运行。将一切都放在一次运行中会不会更好?

有更好的方法吗?

2 个答案:

答案 0 :(得分:5)

DBIOAction具有map / flatMap个函数,因此您可以编写类似

的内容
val insertAction = foo.flatMap(bar ++= _)

insertAction将是DBIOAction[Int, NoStream, Effect.Write]类型或类似的东西(我不完全确定Int和效果),然后您可以在数据库上运行它与使用DBIOAction的任何db.run一样;你得到的是整个查询和插入结果的未来。

答案 1 :(得分:3)

这些问题已经得到解答,但我来到这里寻找不同的解决方案,所以这可能会对其他人有所帮助。

正如@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)