是否可以在预编译的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]] ^
答案 0 :(得分:9)
您现在无法使用inSet预编译查询,无论是在Slick 1还是在Slick 2中。当您考虑到SQL中针对不同的Set大小的查询必须不同时,这是有意义的。
WHERE false
WHERE id = ?
WHERE id IN (?,?)
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结果,与数据库级别的节省(使用绑定参数)相比,这仍然是一个小成本。