Scala+Slick 3:将一个查询的结果插入另一个 table
Scala+Slick 3: Inserting the result of one query into another table
这个问题是关于 slick 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
。但是现在我有两个 DB-运行s。将所有内容放在一个 运行 中不是更好吗?
有更好的方法吗?
DBIOAction
有 map
/flatMap
函数,所以你可以这样写
val insertAction = foo.flatMap(bar ++= _)
insertAction
将是 DBIOAction[Int, NoStream, Effect.Write]
或类似的类型(我不完全确定 Int
和效果),然后你可以 运行它在数据库上作为任何 DBIOAction
使用 db.run
;然后你得到的是整个查询和插入结果的未来。
问题已经得到解答,但我来这里是为了寻找不同的解决方案,所以这可能对其他人有所帮助。
正如@Aldo 所说,我们希望尽可能在 DBIO 级别工作,但我会更进一步说你应该尽可能在 Query
级别工作,因为它编译为可以发送到数据库的单个 sql 语句。
例如,来自 select 的插入应编译为 INSERT INTO table1 SELECT...
。如果您使用 flatMap
的多个 DBIOS,就像建议的那样,这将被编译成一个 SELECT
,这些值将被带到内存中,然后一个 INSERT
语句将被编译,插入这些值在一个字符串中,这个新查询将被发送到数据库。实际上,如果您的 select returns 许多结果,这可能会慢得多,并且在最坏的情况下它会耗尽您的内存。
因此,要将类似这样的内容编译成单个查询,您可以编写:
val bar: TableQuery[MySchema.Bar]
val foo: Query[MySchema.Bar, Bar, Seq]
val insert: DBIO[Int] = bar.forceInsertAll(foo)
这个问题是关于 slick 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
。但是现在我有两个 DB-运行s。将所有内容放在一个 运行 中不是更好吗?
有更好的方法吗?
DBIOAction
有 map
/flatMap
函数,所以你可以这样写
val insertAction = foo.flatMap(bar ++= _)
insertAction
将是 DBIOAction[Int, NoStream, Effect.Write]
或类似的类型(我不完全确定 Int
和效果),然后你可以 运行它在数据库上作为任何 DBIOAction
使用 db.run
;然后你得到的是整个查询和插入结果的未来。
问题已经得到解答,但我来这里是为了寻找不同的解决方案,所以这可能对其他人有所帮助。
正如@Aldo 所说,我们希望尽可能在 DBIO 级别工作,但我会更进一步说你应该尽可能在 Query
级别工作,因为它编译为可以发送到数据库的单个 sql 语句。
例如,来自 select 的插入应编译为 INSERT INTO table1 SELECT...
。如果您使用 flatMap
的多个 DBIOS,就像建议的那样,这将被编译成一个 SELECT
,这些值将被带到内存中,然后一个 INSERT
语句将被编译,插入这些值在一个字符串中,这个新查询将被发送到数据库。实际上,如果您的 select returns 许多结果,这可能会慢得多,并且在最坏的情况下它会耗尽您的内存。
因此,要将类似这样的内容编译成单个查询,您可以编写:
val bar: TableQuery[MySchema.Bar]
val foo: Query[MySchema.Bar, Bar, Seq]
val insert: DBIO[Int] = bar.forceInsertAll(foo)