2

我遇到了一种奇怪的行为,我需要一些帮助来弄清楚为什么会发生这种情况。问题是我有一个查询如下:

db.withSession { implicit session =>
  tables.users.where(_.id === UserId(1)).firstOption
}

这不会编译产生如下错误:

inferred type arguments [Boolean] do not conform to method where's type parameter bounds [T <: scala.slick.lifted.Column[_]]

但是,如果我将代码重写为:

db.withSession { implicit session =>
  (for {
    u <- tables.users if u.id === UserId(1)
  } yield u).firstOption
}

它编译并且工作正常。

该表定义如下:

class Users(tag: Tag) extends Table[User](tag, "users") {
  def id = column[UserId]("id", O.PrimaryKey, O.AutoInc, O.NotNull)
}

我有一个隐式转换来映射 UserId 类型:

implicit lazy val userIdColumnType = MappedColumnType.base[UserId, Int](_.value, UserId(_))

它看起来像一个类型推断问题,但我无法真正理解它为什么会发生。

任何人都知道为什么在我报告的两种情况下这应该表现不同?

编辑:经过一番调查,我发现当使用where隐式转换时userIdColumnType,必须在范围内,而使用 for 理解则不需要。对此有很好的解释吗?

4

2 回答 2

5

您正在使用来自 ScalaTest 的 ===。它返回一个布尔值。Slick 的 === 返回一个Column[Boolean]. 方法filterwhere防止使用布尔值(至少在最新版本的 Slick 中),以防止您意外使用==或在您的情况下使用 ScalaTest ===,它对基础值进行本地比较,而不是在数据库中进行相等比较,这就是你真正想要的。因为推导被取消糖分withFilter并且有时可以生成布尔值,所以不幸的是我们不能禁止推导Boolean

要解决此问题,您需要确保===在查询中选择了 Slick。也许您可以通过导入顺序或范围来影响这一点。或者,如果你不走运,你不能,它们是不相容的。

我不确定 userIdColumnType 目前是如何在这里交互的。

于 2014-07-24T17:29:48.273 回答
0

我通过导入我的驱动程序 api 并确保它在范围内来解决这个问题

即,当我使用的是 postgresql 驱动程序时, import PostgresProfile.api._

于 2017-07-20T09:25:25.023 回答