Sha*_*yUT 28 scala typesafe-stack slick
我试图学习使用Slick来查询MySQL.我有以下类型的查询工作来获取单个Visit对象:
Q.query[(Int,Int), Visit]("""
select * from visit where vistor = ? and location_code = ?
""").firstOption(visitorId,locationCode)
Run Code Online (Sandbox Code Playgroud)
我想知道的是如何更改以上内容以查询以获取Locations集合的List [Visit] ...类似这样的内容:
val locationCodes = List("loc1","loc2","loc3"...)
Q.query[(Int,Int,List[String]), Visit]("""
select * from visit where vistor = ? and location_code in (?,?,?...)
""").list(visitorId,locationCodes)
Run Code Online (Sandbox Code Playgroud)
Slick有可能吗?
Fai*_*aiz 29
正如另一个答案所暗示的那样,这对于静态查询来说很麻烦.静态查询接口要求您将绑定参数描述为Product.(Int, Int, String*)
是无效的scala,并且使用也(Int,Int,List[String])需要一些kludges.此外,必须确保locationCodes.size始终等于查询中的数量(?, ?...)是脆弱的.
实际上,这并不是一个问题,因为您希望使用查询monad,这是使用Slick的类型安全和推荐的方法.
val visitorId: Int = // whatever
val locationCodes = List("loc1","loc2","loc3"...)
// your query, with bind params.
val q = for {
v <- Visits
if v.visitor is visitorId.bind
if v.location_code inSetBind locationCodes
} yield v
// have a look at the generated query.
println(q.selectStatement)
// run the query
q.list
Run Code Online (Sandbox Code Playgroud)
这假设你的表设置如下:
case class Visitor(visitor: Int, ... location_code: String)
object Visitors extends Table[Visitor]("visitor") {
def visitor = column[Int]("visitor")
def location_code = column[String]("location_code")
// .. etc
def * = visitor ~ .. ~ location_code <> (Visitor, Visitor.unapply _)
}
Run Code Online (Sandbox Code Playgroud)
请注意,您始终可以将查询包装在方法中.
def byIdAndLocations(visitorId: Int, locationCodes: List[String]) =
for {
v <- Visits
if v.visitor is visitorId.bind
if v.location_code inSetBind locationCodes
} yield v
}
byIdAndLocations(visitorId, List("loc1", "loc2", ..)) list
Run Code Online (Sandbox Code Playgroud)
它不起作用,因为StaticQuery object(Q)期望隐式设置查询字符串中的参数,使用方法的类型参数query来创建一种setter对象(类型scala.slick.jdbc.SetParameter[T]).
其作用SetParameter[T]是将查询参数设置为type的值T,其中所需类型取自query[...]类型参数.
从我看到有一个为定义没有这样的对象T = List[A]为一个通用的A,这似乎是一个明智的选择,因为你不能真正与参数的动态列表写一个SQL查询IN (?, ?, ?,...)子句
我通过以下代码提供了这样一个隐式值来做实验
import scala.slick.jdbc.{SetParameter, StaticQuery => Q}
def seqParam[A](implicit pconv: SetParameter[A]): SetParameter[Seq[A]] = SetParameter {
case (seq, pp) =>
for (a <- seq) {
pconv.apply(a, pp)
}
}
implicit val listSP: SetParameter[List[String]] = seqParam[String]
Run Code Online (Sandbox Code Playgroud)
在范围内,您应该能够执行您的代码
val locationCodes = List("loc1","loc2","loc3"...)
Q.query[(Int,Int,List[String]), Visit]("""
select * from visit where vistor = ? and location_code in (?,?,?...)
""").list(visitorId,locationCodes)
Run Code Online (Sandbox Code Playgroud)
但是,你必须手动保证locationCodes大小相同数量?的中IN条款
最后,我相信可以使用宏创建更清晰的解决方法,以概括序列类型.但鉴于前面提到的序列大小的动态性问题,我不确定它是否是框架的明智选择.
| 归档时间: |
|
| 查看次数: |
19313 次 |
| 最近记录: |