这个问题是关于光滑的3.0或3.1(我对此很灵活)
我有一个中间查询,我使用map
,for
等处理,以获得我想要的结果。最后我有一个
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运行。将一切都放在一次运行中会不会更好?
有更好的方法吗?
答案 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)