Слегка левое внешнее соединение, получающее целую объединенную строку в качестве опции
Мое соединение выглядит так:
def byIdWithImage = for {
userId <- Parameters[Long]
(user, image) <- Users leftJoin RemoteImages on (_.imageId === _.id) if user.id === userId
} yield (user, image)
но slick не работает во время выполнения, когда user.imageId имеет значение null
[SlickException: чтение значения NULL для столбца RemoteImage.url]
Изменение выхода на
} yield (user, image.?)
дает мне исключение времени компиляции, оно работает только с отдельными столбцами
не удалось найти неявное значение для параметра доказательства типа scala.slick.lifted.TypeMapper [image.type]
Будет ли другой способ выполнить то, что я пытаюсь сделать здесь? (в одном запросе)
Ответы
Ответ 1
С помощью приведенного ниже кода вы можете указать: 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
}
}
Ответ 2
Сверху моей головы я бы использовал настраиваемую проекцию. Что-то вроде этого:
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
) должно помочь уменьшить часть этого шаблона.
Ответ 3
Я объединил помощников для этого в приложении для примера play-slick, которое позволяет вам просто вызвать image.?
См. .? звонки, определение? и определение mapOption.