在 Slick 3.1 中声明 Date/Time 列会引发编译错误

Declaring Date/Time columns in Slick 3.1 throws compilation error

我有以下代码,其中包括一个案例 class(MyEmail)、相关的 Slick class (MyEmailDB) 和用于转换 LocalDateTime 的隐式函数。问题是 def * = 函数抛出编译错误。如果我删除程序编译的隐式函数之一,但如何解决这个问题?

case class MyEmail (sk: Int, subject: String, message: String, 
                    createTS: LocalDateTime, updateTS: Option[LocalDateTime])

class MyEmailDB(tag: Tag) extends Table[MyEmail](tag, "emails") {

    def sk = column[Int]("sk", O.PrimaryKey, O.AutoInc)
    def subject = column[String]("subject")
    def message = column[String]("message")
    def createTS = column[LocalDateTime]("create_ts")(localDateTimeColumnType)
    def updateTS = column[Option[LocalDateTime]]("update_ts")(localDateTimeColumnType2)

    def * = (sk, subject, message, createTS, updateTS) <> ((MyEmail.apply _).tupled, MyEmail.unapply)  // <-- this line throws the compilation error

    implicit val localDateTimeColumnType = MappedColumnType.base[LocalDateTime, Timestamp](
     {
        case localDateTime => Timestamp.valueOf(localDateTime)
     },{
        ts => ts.toLocalDateTime
     }
   )

   implicit val localDateTimeColumnType2 = MappedColumnType.base[Option[LocalDateTime], Timestamp](
     {
        case Some(localDateTime) => Timestamp.valueOf(localDateTime)
        case None => null
     },{
        ts => if (ts != null) Some(ts.toLocalDateTime) else None
     }
   )   
}

错误是:

◾Implicit conversion found: ⇒ anyToToShapedValue(): slick.lifted.ToShapedValue[(slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[String], slick.lifted.Rep[java.time.LocalDateTime])] ◾not enough arguments for method <>: (implicit evidence: scala.reflect.ClassTag[tasks.addit.email.MyEmail], implicit shape: slick.lifted.Shape[_ <: slick.lifted.FlatShapeLevel, (slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[String], slick.lifted.Rep[java.time.LocalDateTime]), (Int, String, String, java.time.LocalDateTime, Option[java.time.LocalDateTime]), _])slick.lifted.MappedProjection[tasks.addit.email.MyEmail,(Int, String, String, java.time.LocalDateTime, Option[java.time.LocalDateTime])]. Unspecified value parameter shape. ◾implements slick.lifted.AbstractTable.$times ◾No matching Shape found. Slick does not know how to map the given types. Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List). Required level: slick.lifted.FlatShapeLevel Source type: (slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[String], slick.lifted.Rep[java.time.LocalDateTime]) Unpacked type: (Int, String, String, java.time.LocalDateTime, Option[java.time.LocalDateTime]) Packed type: Any

Giving explicit return type as BaseColumnType[LocalDateTime] for the implicit solved the compilation error

用显式 return 类型声明隐式。

为了清晰起见,您可以进一步改进代码。

  implicit val localDateTimeColumnType: BaseColumnType[LocalDateTime] = MappedColumnType.base[LocalDateTime, Timestamp](Timestamp.valueOf, _.toLocalDateTime)

  case class MyEmail(sk: Int, subject: String, message: String,
    createTS: LocalDateTime, updateTS: Option[LocalDateTime])

  class MyEmailDB(tag: Tag) extends Table[MyEmail](tag, "emails") {

    def sk = column[Int]("sk", O.PrimaryKey, O.AutoInc)
    def subject = column[String]("subject")
    def message = column[String]("message")
    def createTS = column[LocalDateTime]("create_ts")
    def updateTS = column[Option[LocalDateTime]]("update_ts")

    def * = (sk, subject, message, createTS, updateTS) <> ((MyEmail.apply _).tupled, MyEmail.unapply)
  }

请注意,Option[LocalDateTime]

不需要特殊的隐式