Scala Slick 组合列类型映射器

Scala Slick compose column type mappers

我正在使用 slick-pg,它为 slick 中的 ListDateTime 类型添加了支持(带有隐式)。

不幸的是,我不能使用 List[DateTime] - slick 不理解这些类型的组成,但我已经检查过这两种类型都可以正常工作(例如 List[Int]DateTime ).

有没有办法轻松组合这两个隐式?

1.尝试添加

  implicit def dateTimeList =
    MappedColumnType.base[List[DateTime], List[Timestamp]](
      _.map(dt => new Timestamp(dt.getMillis)),
      _.map(ts => new DateTime(ts.getTime))
    )

以防万一,整个编译代码:

import java.sql.Timestamp
import org.joda.time.DateTime
import slick.jdbc.PostgresProfile.api._
import slick.lifted.ProvenShape
import slick.basic.Capability
import slick.jdbc.JdbcCapabilities
import com.github.tototoshi.slick.PostgresJodaSupport._
import com.github.tminglei.slickpg._

object App {

  trait MyPostgresProfile extends ExPostgresProfile
    with PgArraySupport
    with PgDate2Support
    with PgRangeSupport
    with PgHStoreSupport
//    with PgPlayJsonSupport
    with PgSearchSupport
//    with PgPostGISSupport
    with PgNetSupport
    with PgLTreeSupport {
    def pgjson = "jsonb" // jsonb support is in postgres 9.4.0 onward; for 9.3.x use "json"

    // Add back `capabilities.insertOrUpdate` to enable native `upsert` support; for postgres 9.5+
    override protected def computeCapabilities: Set[Capability] =
      super.computeCapabilities + /*JdbcProfile.capabilities.insertOrUpdate*/ JdbcCapabilities.insertOrUpdate

    override val api = MyAPI

    object MyAPI extends API with ArrayImplicits
      with DateTimeImplicits
//      with JsonImplicits
      with NetImplicits
      with LTreeImplicits
      with RangeImplicits
      with HStoreImplicits
      with SearchImplicits
      with SearchAssistants {
      implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList)
//      implicit val playJsonArrayTypeMapper =
//        new AdvancedArrayJdbcType[JsValue](pgjson,
//          (s) => utils.SimpleArrayUtils.fromString[JsValue](Json.parse(_))(s).orNull,
//          (v) => utils.SimpleArrayUtils.mkString[JsValue](_.toString())(v)
//        ).to(_.toList)
    }
  }

  object MyPostgresProfile extends MyPostgresProfile

  import MyPostgresProfile.api._

   // This can be used instead of slick-joda-mapper library 
//  implicit def dateTime =
//    MappedColumnType.base[DateTime, Timestamp](
//      dt => new Timestamp(dt.getMillis),
//      ts => new DateTime(ts.getTime)
//    )

  implicit def dateTimeList =
    MappedColumnType.base[List[DateTime], List[Timestamp]](
      _.map(dt => new Timestamp(dt.getMillis)),
      _.map(ts => new DateTime(ts.getTime))
    )

  case class Record(id: Int, name: String, friends: List[Int], registered: DateTime, visits: List[DateTime])

  class RecordTable(tag: Tag) extends Table[Record](tag, Some("public"), "records") {
    def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
    def name: Rep[String] = column[String]("name")
    def friends: Rep[List[Int]] = column[List[Int]]("friends")
    def registered: Rep[DateTime] = column[DateTime]("registered")
    def visits: Rep[List[DateTime]] = column[List[DateTime]]("visits")
    def * : ProvenShape[Record] = (id, name, friends, registered, visits) <> (Record.tupled, Record.unapply)
  }

  val records: TableQuery[RecordTable] = TableQuery[RecordTable]
}

build.sbt

name := "slickdemo"

version := "0.1"

scalaVersion := "2.12.3"

libraryDependencies += "com.typesafe.slick" %% "slick" % "3.2.1"
libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25"
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.2.1"

libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"

libraryDependencies += "com.github.tminglei" %% "slick-pg" % "0.15.3"

libraryDependencies += "joda-time" % "joda-time" % "2.9.9"
libraryDependencies += "org.joda" % "joda-convert" % "1.9.2"
libraryDependencies += "com.github.tototoshi" % "slick-joda-mapper_2.12" % "2.3.0"

基于answer and documentation.


2. 或者您可以添加

    implicit val dateTimeArrayTypeMapper =
        new AdvancedArrayJdbcType[DateTime]("timestamp",
          (s) => utils.SimpleArrayUtils.fromString[DateTime](DateTime.parse)(s).orNull,
          (v) => utils.SimpleArrayUtils.mkString[DateTime](_.toString)(v)
        ).to(_.toList)

strListTypeMapperplayJsonArrayTypeMapper 之后。