How can I create a custom column type with Typesafe Slick in Scala?

感情迁移 提交于 2019-12-05 19:02:36

问题


I have a PostgreSQL table with an enum, which is created by:

CREATE TYPE file_status AS ENUM ('new', 'uploading', 'queued', 'processing', 'done', 'failed');

and an associated field

CREATE TABLE files ( ...
    status file_status NOT NULL,
    ...
);

With Scala 2.10 and Typesafe Slick 1.0.1, I've created mappings to my Files table that work great with the exception of the status field, which requires the custom file_status type, a string.

def status = column[FileStatus]("status")

I've been playing with Slick's TypeMapper, but can't quite figure out how to get it to work:

sealed trait FileStatus

implicit val fileStatusMapper: TypeMapper[String] = base[FileStatus, String](
  s => s.toString,
  f => f(FileStatus)
) 

I get the error: type mismatch; found : models.Files.FileStatus.type required: Int

Why is an Int required? Is it because of the TypeMapper? I have also tried

...
f => f.toString
// type mismatch; found : String required: models.Files.FileStatus

f => f
// type mismatch; found : String required: models.Files.FileStatus

Thank you for any pointers in helping me understand this mapping.


回答1:


Quoting from the docs (http://slick.typesafe.com/doc/1.0.1/lifted-embedding.html#user-defined-functions-and-types):

// An algebraic data type for booleans
sealed trait Bool
case object True extends Bool
case object False extends Bool

// And a TypeMapper that maps it to Int values 1 and 0
implicit val boolTypeMapper = MappedTypeMapper.base[Bool, Int](
  { b => if(b == True) 1 else 0 },    // map Bool to Int
  { i => if(i == 1) True else False } // map Int to Bool
)

Adapting this to file status:

sealed trait FileStatus
case object New extends FileStatus
case object Uploading extends FileStatus
...

implicit val fileStatusTypeMapper = MappedTypeMapper.base[FileStatus, String](
  {
    case New => "new"
    case Uploading => "uploading"
    ...
  },{
    case "new" => New
    case "uploading" => Uploading
    ...
  }
)

Update:

Another, less redundant, but possibly also less clear version:

sealed trait FileStatus
case object New extends FileStatus
case object Uploading extends FileStatus
...

val statusMap = Map(
    New -> "new",
    Uploading -> "uploading",
    ...
)

implicit val fileStatusTypeMapper = MappedTypeMapper.base[FileStatus, String](
  statusMap,
  statusMap.map(_.swap)
)



回答2:


Slick 3.x version:

    sealed trait FileStatus
    case object New extends FileStatus
    case object Uploading extends FileStatus
    ...

   implicit val fileStatusColumnType = MappedColumnType.base[FileStatus, String](
   {
     case New => "new"
     case Uploading => "uploading"
     ...
    },{
     case "new" => New
     case "uploading" => Uploading
     ...
   }
 )


来源:https://stackoverflow.com/questions/19030875/how-can-i-create-a-custom-column-type-with-typesafe-slick-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!