2013-02-20 15 views
11

mio aderire simile a questa:Slick join esterno sinistro recupero fila tutto unito come opzione

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

ma chiazza di petrolio non riesce a runtime quando user.imageId è nullo

[SlickException: lettura valore NULL per RemoteImage.url colonna]

Cambiando il rendimento a

} yield (user, image.?) 

mi dà un'eccezione fase di compilazione, funziona solo su singole colonne

non riusciva a trovare valore implicito per il parametro prove di tipo scala.slick.lifted.TypeMapper [image.type]

Ci sarebbe un modo diverso per realizzare ciò che sto cercando di fare qui? (in una singola query)

+1

Un po 'la metà fissato nella chiazza di petrolio 2.0 => http://slick.typesafe.com/talks/ 2013-12-03_Scala-eXchange/2013-12-03_Patterns-for-Slick-database-applications-Scala-eXchange.pdf – Somatik

+0

correlati a http://stackoverflow.com/questions/20386593/ – cvogt

risposta

7

Con il codice qui sotto si può mettere come: rendimento (utente, 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

In cima alla mia testa, userei una proiezione mappata personalizzata. Qualcosa di simile a questo:

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))) 
) 

Utilizzando scalaz (e la sua ApplicativeBuilder) dovrebbe contribuire a ridurre alcuni di quel testo standard.

+6

grazie, sarebbe bello se chiazza fornirebbe un aiuto per questo caso – Somatik

1

ho integrato aiutanti per questo nel mio gioco-slick esempio app che consentono di chiamare solo image.?

Vedi the .? calls, the definition of ? e the definition of mapOption.

+0

farà parte di slick 2.0? – Somatik

+0

Non questa implementazione, ma probabilmente il nostro generatore di codice genererà il necessario? metodi. Quindi in un certo senso, probabilmente sì. – cvogt

Problemi correlati