【问题标题】:How can I create a custom column type with Typesafe Slick in Scala?如何在 Scala 中使用 Typesafe Slick 创建自定义列类型?
【发布时间】:2013-09-26 14:22:01
【问题描述】:

我有一个带有 enum 的 PostgreSQL 表,它由以下人员创建:

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

和相关的字段

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

使用 Scala 2.10 和 Typesafe Slick 1.0.1,我创建了到我的 Files 表的映射,除了 status 字段,它需要自定义 file_status 类型,一个字符串。

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

我一直在玩 Slick 的 TypeMapper,但不知道如何让它工作:

sealed trait FileStatus

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

我得到错误:类型不匹配;找到:models.Files.FileStatus.type required: Int

为什么需要 Int?是因为TypeMapper吗?我也试过了

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

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

感谢您在帮助我理解此映射时提供的任何指示。

【问题讨论】:

    标签: postgresql scala playframework slick


    【解决方案1】:

    引用文档 (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
    )
    

    根据文件状态调整:

    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
        ...
      }
    )
    

    更新:

    另一个不太冗余但也可能不太清晰的版本:

    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 版本:

        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
         ...
       }
     )
    

    【讨论】:

      猜你喜欢
      • 2014-04-21
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      • 2013-03-21
      相关资源
      最近更新 更多