joinLeft错误:构造函数无法实例化为期望的类型

时间:2016-09-09 15:08:33

标签: scala slick

我正在将一些代码从Slick 2.1转换为3.0.3,当我将我的联接从使用leftJoin迁移到joinLeft时,我收到此错误,我不知道如何解决它:

[error] ContentRepoLocal.scala:84: constructor cannot be instantiated to expected type;  
[error]  found   : (T1, T2)  
[error]  required: slick.lifted.Rep[Option[(repo.model.UserContentTable, repo.model.ContentTable)]]  
[error]           .map { case (u, (uc, c)) => (u, c.optionProjection) }  
[error]                           ^  
[error] ContentRepoLocal.scala:84: diverging implicit expansion for type slick.lifted.Shape[_ <: slick.lifted.FlatShapeLevel, Nothing, T, G]  
[error] starting with method repColumnShape in trait RepShapeImplicits  
[error]           .map { case (u, (uc, c)) => (u, c.optionProjection) }

关于此代码:

def getContentsByUser(userId: UUID): Either[UserNotFoundError, List[Content]] = {

 val subQuery =
   for {
     uc <- UserContentTable.query if uc.userId === userId.toString && (!uc.adopted.isDefined || !uc.adopted)
     c <- ContentTable.query if uc.contentId === c.id
   } yield (uc, c)


 val query =
   UserTable.query.filter(_.id === userId.toString)
     .joinLeft(subQuery).on { case (u, (uc, c)) => u.id === uc.userId}
     .map { case (u, (uc, c)) => (u, c.optionProjection) }

 //...

}

编辑1:

通过重构我的subQuery以使用for理解语法来进一步解决这个问题:

val query =
  for (
    (u, t) <- UserTable.query.filter(_.id === userId.toString) joinLeft subQuery on { case (u, (uc, c)) => u.id === uc.userId }
  ) yield (u, t)

这个编译。但是,根据documentationyield应该t.map(_)Null值转换为None

所以,当我重构这行时,请阅读:

yield (u, t.map(_))

我收到错误:

[error] missing parameter type for expanded function ((x$2) => t.map(x$2))
[error]       ) yield (u, t.map(_))
[error]                         ^
[error] one error found

编辑2:您可以找到最小,完整且可验证的示例here

编辑3 :确认此问题在3.1.1中也存在

1 个答案:

答案 0 :(得分:2)

joinLeft在{Slick3}中以subQuery加入Option。在这种情况下,您必须重新映射subQuery,如下所示:

val query =
   UserTable.query.filter(_.id === userId.toString)
     .joinLeft(subQuery).on { case (u, (uc, c)) => u.id === uc.userId}
     .map { case (u, sub) => (u, sub.map { case (uc, c) => c }) }