使用Slick进行左外连接并将整个关联行作为选项提取

11

我的联接看起来像这样:

def byIdWithImage = for {
    userId <- Parameters[Long]
    (user, image) <- Users leftJoin RemoteImages on (_.imageId === _.id) if user.id === userId
} yield (user, image)

但是当user.imageId为空时,Slick在运行时会失败:

[SlickException: 读取RemoteImage.url列的空值]

将yield更改为

} yield (user, image.?)

在编译时会出现异常,它只适用于单个列

找不到类型为scala.slick.lifted.TypeMapper[image.type]的证据参数的隐式值

是否有其它方法可以在一个查询中完成我在这里尝试做的事情?


1
有点在Slick 2.0中被修复 => http://slick.typesafe.com/talks/2013-12-03_Scala-eXchange/2013-12-03_Patterns-for-Slick-database-applications-Scala-eXchange.pdf - Somatik
与https://dev59.com/WGIj5IYBdhLWcg3wUjoX相关的编程内容。 - cvogt
3个回答

8
使用下面的代码可以像这样放置:yield (user,image.maybe)。
case class RemoteImage(id: Long, url: URL)

class RemoteImages extends Table[RemoteImage]("RemoteImage") {
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def url = column[URL]("url", O.NotNull)
    def * = id.? ~ url <> (RemoteImage.apply _, RemoteImage.unapply _)

    def maybe = id.? ~ url.? <> (applyMaybe,unapplyBlank)

    val unapplyBlank = (c:Option[RemoteImage])=>None        

    val applyMaybe = (t: (Option[Long],Option[URL])) => t match {
        case (Some(id),Some(url)) => Some(RemoteImage(Some(id),url))
        case _ => None
    } 
}

8

从我个人的角度来看,我会使用自定义映射投影。例如:

case class RemoteImage(id: Long, url: URL)

def byIdWithImage = for {
    userId <- Parameters[Long]
    (user, image) <- Users leftJoin RemoteImages on (_.imageId === _.id) if user.id === userId
} yield (user, maybeRemoteImage(image.id.? ~ image.url.?))

def maybeRemoteImage(p: Projection2[Option[Long], Option[URL]]) = p <> ( 
  for { id <- _: Option[Long]; url <- _: Option[URL] } yield RemoteImage(id, url),
  (_: Option[RemoteImage]) map (i => (Some(i id), Some(i url)))
)

使用scalaz(及其ApplicativeBuilder)可以帮助减少一些样板代码。


6
谢谢,如果Slick能为这种情况提供一个帮助程序就太好了。 - Somatik

1

这将成为Slick 2.0的一部分吗? - Somatik
不是这个实现方式,但很可能我们的代码生成器会生成所需的?方法。因此,在某种程度上,很可能是的。 - cvogt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接