是否可以在Slick查询模板中使用List或Set类型的参数? (提升的API)

时间:2013-11-12 10:08:39

标签: scala slick

是否可以在预编译的Slick查询中将集合用作参数?

类似的东西:

private val findByIds = for {
  ids <- Parameters[Set[Int]]
  meta <- AssetMetadatas if meta.id inSet ids
} yield meta

不幸的是上面没有编译:

不知道如何将scala.collection.immutable.Set [Int]解压缩到scala.collection.immutable.Set [Int]并打包到Any       ids&lt; - 参数[Set [Int]]                        ^

2 个答案:

答案 0 :(得分:9)

您现在无法使用inSet预编译查询,无论是在Slick 1还是在Slick 2中。当您考虑到SQL中针对不同的Set大小的查询必须不同时,这是有意义的。

  • 代表0:WHERE false
  • for 1:WHERE id = ?
  • for 2:WHERE id IN (?,?)
  • for 3:WHERE id IN (?,?,?)
  • ...

这通常不能预编译,因此Slick每次都必须为它编译SQL。我们可能会在某些时候为某些后端支持它。如果它很重要,您可以自行预编译一些选定的设置尺寸(使用&&==代替inSet)。

使用inSetBind而不是inSet会将set作为参数传递给预准备语句,而不是将它们作为文字编译到SQL字符串中。如果您以这种方式配置,这允许您的连接池缓存预准备的语句。所以Slick仍然需要编译查询,但至少你的数据库可以缓存查询计划。

答案 1 :(得分:2)

那是inSetBind

private def findByIds(ids: Set[Int]) = for {
  meta <- AssetMetadatas if meta.id inSetBind ids
} yield meta

是的,这将在每次调用findByIds时调用查询编译器,但它将始终为ids的相同基数生成相同的SQL。

因此,对于ids Set(1,2,3),将生成生成的SQL,

SELECT * from AssetMetadatas WHERE ID IN (?, ?, ?)

在调用查询时将绑定到(1, 2, 3)。当您调用findByIds(Set(4,5,6))时,查询编译器将再次运行,但将生成完全相同的SQL。 即使假设光滑不会缓存已编译的AST结果,与数据库级别的节省(使用绑定参数)相比,这仍然是一个小成本。