【问题标题】:Slick does not know how to map the given types - Option(DateTime.now)Slick 不知道如何映射给定的类型 - Option(DateTime.now)
【发布时间】:2019-08-04 17:22:38
【问题描述】:

我正在尝试这样做(在 Play Framework 上):

db.run(users.filter(_.id === id).map(_.deleted).update(Option(DateTime.now)))

但是它抛出了一个编译错误:

找不到匹配的形状。 Slick 不知道如何映射给定的 类型。可能的原因: Table[T] 中的 T 与您的 * 不匹配 投影,您在查询中使用不受支持的类型(例如 scala 列表), 或者您忘记将驱动程序 api 导入范围。要求等级: slick.lifted.FlatShapeLevel 源类型:slick.lifted.Rep[Option[org.joda.time.DateTime]] 解包类型:T 包装类型:G

Slick 3.0.3 版本。 我该如何解决这个错误?

class UserTable(tag: Tag) extends Table[User](tag, "user") {

  def id = column[Int]("id")

  def name = column[String]("name")

  def age = column[Int]("age")

  def deleted = column[Option[DateTime]]("deleted")

  override def * =
    (id, name, age, deleted) <> ((User.apply _).tupled, User.unapply)
}

case class User(
  id: Int = 0,
  name: String,
  age: Int,
  deleted: Option[DateTime] = None
)

【问题讨论】:

    标签: scala playframework slick


    【解决方案1】:

    当您定义表时,DateTime 的范围内有一个列类型映射器。类似的东西

    implicit val dtMapper = MappedColumnType.base[org.joda.time.DateTime, Long](
      dt => dt.getMillis,
      l => new DateTime(l, DateTimeZone.UTC)
    )
    

    例如。此映射器还必须在您构建查询的位置范围内,否则 Slick 将不知道如何将您编写的内容转换为 SQL 查询。

    如果您想将查询与表分开,您可以导入映射器,或者在定义UserTable 的同一文件中定义查询。一种常见的模式是将表包装在一个 trait 中,比如 UserRepository,并在该 trait 中定义表和查询。

    See this page 了解有关隐式作用域如何工作的更多信息。

    【讨论】:

    • 我在UserTable中添加了这段代码,但错误仍然存​​在
    • class UserTable(tag: Tag) extends Table[User](tag, "user") { implicit val dtMapper = MappedColumnType.base[DateTime, Long](d =&gt; d.getMillis, d =&gt; new DateTime(d)) def id: Rep[Int] = column[Int]("id") def name: Rep[String] = column[String]("name") def age: Rep[Int] = column[Int]("age") def deleted: Rep[Option[DateTime]] = column[Option[DateTime]]("deleted") override def * = (id, name, age, deleted) &lt;&gt; ((User.apply _).tupled, User.unapply) }
    • 映射器必须可用,即在“隐式范围”内,在定义update 查询的位置,以及定义表的位置。要更好地理解隐式作用域,请参阅docs.scala-lang.org/tutorials/FAQ/finding-implicits.html
    • 谢谢,一切正常。我刚刚将 implicit val dtMapper: JdbcType[DateTime] with BaseTypedType[DateTime] = MappedColumnType.base[DateTime, Long](d =&gt; d.getMillis, d =&gt; new DateTime(d)) 添加到进行更新的函数中(在 DAO 中)。
    • 我很高兴它成功了!但请确保表和查询使用相同的映射器;如果映射器不同(例如一个映射到纪元毫秒,另一个映射到秒),就会有错误。
    猜你喜欢
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多