【问题标题】:Scala Slick 3.1 multiple joinsScala Slick 3.1 多连接
【发布时间】:2016-04-05 08:01:59
【问题描述】:

我正在尝试在 Slick 3.1.1 中执行多个连接。我想要达到的结果是这样的:

SELECT * FROM customer LEFT JOIN customer_address ON customer.id = customer_address.customer_id LEFT JOIN address ON customer_address.address_id = address.id

我尝试了以下方法:

val query = for {
  c <- Customer
  ca <- CustomerAddress if ca.customerId === c.id
  a <- Address if a.id === ca.addressId
} yield (c, a)

这里的问题是,如果客户没有地址,那么它就不会出现,这是有道理的。

然后我尝试了这个:

    val query2 = for {
       (c, ca, a) <- (Customer joinLeft CustomerAddress on (_.id === _.customerId)) joinLeft Address on (_._2.addressId === _.id)
    } yield (c, a)

这里的问题是我在_._2.addressId 上收到错误,因为_._2 是Rep 对象。

确切的错误:

Error:(21, 110) value addressId is not a member of slick.lifted.Rep[Option[Models.Tables.CustomerAddress]]
  (c, ca, a) <- (Customer joinLeft CustomerAddress on (_.id === _.customerId)) joinLeft Address on (_._2.addressId === _.id)

自动生成的 Slick Tables 类: http://pastebin.com/e4M3cGU8

如何使用 Slick 获得我想要的结果?

【问题讨论】:

  • 您能补充一下您收到的错误吗?

标签: scala slick


【解决方案1】:

你要做的也是映射结果。

val query2 = for {
      ((c, ca), a) <- (Customer joinLeft CustomerAddress on (_.id === _.customerId)) joinLeft Address on (_._2.map(_.addressId) === _.id)
} yield (c, a)

【讨论】:

  • 这是正确的答案,但这种语法令人作呕。我认为 slick 会为我解决问题,但我刚刚遇到了这样的挫折
  • 在 slick 中是否引入了更简洁的方法来做到这一点?这是很常见的用例(至少对我们而言),这让代码非常难看!
【解决方案2】:

这应该可行。 // ((c, ca), a) 而不是 (c, ca, a)

val query2 = for {
   ((c, ca), a) <- (Customer joinLeft CustomerAddress on (_.id === _.customerId)) joinLeft Address on (_._2.addressId === _.id)
} yield (c, a)

【讨论】:

  • @JellevanEs 看起来Table 的配置有误。可以分享Customer、CustomerAddress 和Address 的定义吗?看起来您错过了在其中一个表定义中使用Option?
  • 我添加了 Table 类。我不知道你是否可以用它做点什么,因为它是由 slick 自动生成的
【解决方案3】:

这个答案也和其他答案一样,但更清晰易读。

val query2 = for {
    ((customer, customerAddress), address) <-
        (Customer joinLeft CustomerAddress on
            {
                case(customerTable,customerAddressTable) =>
                    (customerTable.id === customerAddressTable.customerId)
            }
        ) joinLeft Address on
            {
                case ((customerTable,customerAddressTable),addressTable) =>
                    (customerAddressTable.map(_.addressId) === addressTable.id)
            }
} yield (customer, address)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 1970-01-01
    • 2012-12-31
    • 2014-06-16
    • 1970-01-01
    相关资源
    最近更新 更多