2013-02-20 28 views
11

My tham gia trông như sau:Slick ngoài trái join lấy hàng toàn bộ gia nhập như tùy chọn

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

nhưng trơn thất bại trong thời gian chạy khi user.imageId là null

[SlickException: Đọc giá trị NULL cho cột RemoteImage.url]

Thay đổi năng suất để

} yield (user, image.?) 

mang lại cho tôi một thời gian ngoại lệ biên dịch, nó chỉ hoạt động trên các cột riêng

không thể tìm thấy giá trị tiềm ẩn đối với tham số bằng chứng về loại scala.slick.lifted.TypeMapper [image.type]

Có cách nào khác để hoàn thành những gì tôi đang cố gắng làm ở đây không? (trong một truy vấn)

+1

Hơi nửa cố định trong trơn 2.0 => http://slick.typesafe.com/talks/ 2013-12-03_Scala-eXchange/2013-12-03_Patterns-for-Slick-cơ sở dữ liệu-ứng dụng-Scala-eXchange.pdf – Somatik

+0

liên quan đến http://stackoverflow.com/questions/20386593/ – cvogt

Trả lời

7

Với mã bên dưới, bạn có thể đặt nó như thế: năng suất (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

Tắt đầu tôi, tôi sẽ sử dụng phép chiếu được ánh xạ tùy chỉnh. Một cái gì đó như thế này:

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

Sử dụng scalaz (và ApplicativeBuilder) sẽ giúp giảm bớt một số bản mẫu đó.

+6

cảm ơn, sẽ được tốt đẹp nếu slick sẽ cung cấp một trợ giúp cho trường hợp này – Somatik

1

tôi tích hợp giúp việc cho điều này trong trận play-trơn ví dụ ứng dụng của tôi, mà cho phép bạn chỉ cần gọi image.?

Xem the .? calls, the definition of ?the definition of mapOption.

+0

đây sẽ là một phần của slick 2.0? – Somatik

+0

Không thực hiện điều này, nhưng có lẽ bộ tạo mã của chúng tôi sẽ tạo ra yêu cầu? phương pháp. Vì vậy, theo một cách nào đó, có thể là có. – cvogt