Play Slick 处理 Date 与匹配的 Shapes 和 Implicits

Play Slick handling Date with matching Shapes and Implicits

我正在向 Person table 添加两个附加字段:日期和字符串。我构建了 Person 表格,并按照 olivebh's tutorial 使用 Play Slick 将其映射。 但是,我从 Slick 数据模型特征表中得到以下错误:

dao/Tables.scala:85: ambiguous implicit values:
[error]  both value e3 of type slick.jdbc.GetResult[String]
[error]  and value e1 of type slick.jdbc.GetResult[String]
[error]  match expected type slick.jdbc.GetResult[String]
[error]       ProjectRow.tupled((<<[Int], <<[String], <<[Date], <<[String]))

指的是以下行:

  implicit def GetResultPersonRow(implicit e0: GR[Int], e1: GR[String], e2: GR[Date], e3: GR[String]): GR[ProjectRow] = GR {
prs =>
  import prs._
  PersonRow.tupled((<<[Int], <<[String], <<[Date], <<[String]))

}

其中 "int, string, date, string" 分别代表 "id, name, birthdate, language" 字段。按照涵盖 "id, name" 的教程作为示例,一切正常。但是一旦我添加了生日和语言,我就得到了上面引用的错误。

此外,在为 table 行创建原型时:

  class Person(_tableTag: Tag) extends Table[PersonRow](_tableTag, "person") {
    def * = (personId, name, birthdate, language) <>(PersonRow.tupled, PersonRow.unapply)

    def ? = (Rep.Some(personId), Rep.Some(name), Rep.Some(birthdate), Rep.Some(language)).shaped.<>({ r => import r._; _1.map(_ => ProjectRow.tupled((_1.get, _2.get, _3.get, _4.get))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))

    val personId: Rep[Int] = column[Int]("person_id", O.AutoInc, O.PrimaryKey)
    val name: Rep[String] = column[String]("name", O.Length(50, varying = true))
    val birthdate: Rep[Date] = column[Date]("birthdate", O.Length(50, varying = true))
    val language: Rep[String] = column[String]("language", O.Length(50, varying = true))

我收到以下错误:

No matching Shape found.
[error] Slick does not know how to map the given types.
[error] Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List).
[error]   Required level: slick.lifted.FlatShapeLevel
[error]      Source type: (slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[java.util.Date], slick.lifted.Rep[String])
[error]    Unpacked type: (Int, String, java.util.Date, String)
[error]      Packed type: Any
[error]     def * = (personId, name, birthdate, language) <>(PersonRow.tupled, PersonRow.unapply)

还有:

dao/Tables.scala:94: could not find implicit value for parameter od: slick.lifted.OptionLift[Tables.this.driver.api.Rep[java.util.Date],O]
[error]     def ? = (Rep.Some(personId), Rep.Some(name), Rep.Some(birthdate), Rep.Some(language)).shaped.<>({ r => import r._; _1.map(_ => PersonRow.tupled((_1.get, _2.get, _3.get, _4.get))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))
dao/Tables.scala:94: not found: value _1
[error]     def ? = (Rep.Some(personId), Rep.Some(name), Rep.Some(birthdate), Rep.Some(language)).shaped.<>({ r => import r._; _1.map(_ => PersonRow.tupled((_1.get, _2.get, _3.get, _4.get))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))

任何帮助理解这些错误以及如何更改 Slick data model trait 以使其正确处理两个额外的 Date 和 String 字段的帮助,将不胜感激。非常感谢!

Slick 无法处理 java.util.Date,因为数据库只能通过 JDBC 驱动程序理解 java.sql.Date。你可以制作自己的映射器,这样 Slick 就可以知道如何 read/write java.util.Date/java.sql.Date。但是,Java 8 现在有更好的 API 来处理 date/time/calendars。

implicit val localDateTimeColumnType = MappedColumnType.base[LocalDateTime, Timestamp](
    ldt => Timestamp.valueOf(ldt),
    t => t.toLocalDateTime
)

另见 this 问题。顺便说一句,感谢阅读我的文章,希望它有用! :)