Scala Slick сопоставляет сопоставители типов столбцов

Я использую slick-pg, который добавляет поддержку (с неявными значениями) для типов List и DateTime в slick.

К сожалению, я не могу использовать List[DateTime] - slick не понимает состав этих типов, но я проверил, что оба корректно работают сами по себе (например, List[Int] и DateTime).

Есть ли способ легко составить эти два имплицита?


person fr3ak    schedule 17.10.2017    source источник


Ответы (1)


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"

На основе ответа и документация.


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)

после strListTypeMapper и playJsonArrayTypeMapper.

person Dmytro Mitin    schedule 17.10.2017
comment
Мне было интересно, смогу ли я сделать это, не создавая свой собственный сопоставитель, поскольку у меня есть неявный сопоставитель для списка и для DateTime - с некоторым импортом или чем-то еще. Так что я вижу, что, к сожалению, нет. - person fr3ak; 19.10.2017