25

我有以下枚举:

object LoginStatus extends Enumeration() with BitmaskedEnumeration {
  type LoginStatus = Value
  val Active = Value("A")
  val Inactive = Value("I")
}

我需要保留枚举“A”的值,但是当生成 sql 时结果为 0。这是表映射:

object LoginTable extends Table[Login]("login") {
  def idLogin = column[Int]("idlogin", O.PrimaryKey, O.AutoInc)
  def cdLogin = column[String]("cdlogin", O.NotNull)
  def cdPass = column[String]("cdPass", O.NotNull)
  def stLogin = column[LoginStatus]("stlogin", O.NotNull, O.DBType("character(1)"))
}

如何持久化枚举值?

我实施了

implicit val charMapper = MappedTypeMapper.base[Char, String](
    b => b.toString(),
    i => i.charAt(0))

  implicit def enum2StringMapper(enum: Enumeration) = MappedTypeMapper.base[enum.Value, Char](
    b => b.toString.charAt(0),
    i => enum.withName(i.toString))

  implicit val LoginStatusMapper = enum2StringMapper(LoginStatus)

但导致:

[error] c.Login - Invalid value for type int : A
4

4 回答 4

19

我个人建议让您自己的类继承自 Scala 的 Enumeration 类,因为这样您就不必为最终使用的每个枚举创建映射器:

这是我目前正在使用的 slick 2.0 代码:

abstract class DBEnum extends Enumeration {

  import slick.jdbc.MappedJdbcType
  import slick.driver.JdbcDriver.simple._

  implicit val enumMapper = MappedJdbcType.base[Value, Int](_.id, this.apply)
}

这也应该在 slick 1.0 中工作(我还没有测试过):

abstract class DBEnum extends Enumeration {
  implicit val enumMapper = MappedTypeMapper.base[Value, Int](_.id, this.apply)
}

现在,您的枚举所需要的只是从 DBEnum 继承,它应该减少很多样板。

如果您想使用字符串值而不是 Ints,请相应地编辑代码。

于 2013-10-16T18:19:48.350 回答
4

也许您可以为您的枚举类型创建一个 TypeMapper:

implicit val LoginStatusTypeMapper = MappedTypeMapper.base[LoginStatus.Value, Int](  
  // conversion from LoginStatus to int
  {
    status => status.id
  },
  // conversion back from int to enum
  {
    id => LoginStatus(id)
  }
 )

那么您需要将您的列引用为:

columnLoginStatus.Value

这样,当您从数据库加载数据时,它将被转换回您的枚举。如果您坚持将值作为字符存储在数据库中,您只需创建一个映射到 char 的映射器并定义您的

于 2013-10-09T14:50:39.283 回答
2

经过一些帮助,我找到了解决方案,枚举:

object LoginStatus extends Enumeration {

  def enum2StringMapper(enum: Enumeration) = MappedTypeMapper.base[enum.Value, String](
    b => b.toString,
    i => enum.withName(i))

  implicit val LoginStatusMapper = enum2StringMapper(LoginStatus)

  type LoginStatus = Value
  val Active = Value("A")
  val Inactive = Value("I")
}

和表映射:

    import constants.LoginStatus._
...
    def stLogin = column[LoginStatus]("stlogin", O.NotNull, O.DBType("character(1)"))
于 2013-10-10T18:30:00.110 回答
0

@prakhunov 的回答非常好,也适用于 Slick 3.x(在 3.3.3 上测试)。这是他的答案的变体,它将枚举作为字符串存储在数据库中:

import slick.jdbc.H2Profile.api._

// DatabaseEnumeration.scala
abstract class DatabaseEnumeration extends Enumeration {
  implicit val enumerationMapper = MappedColumnType.base[Value, String](_.toString, this.withName)
}

// ColourType.scala
object ColourType extends DatabaseEnumeration {
  type ColourType = Value
  val Red, Blue = Value
}

// NumberType.scala
object NumberType extends DatabaseEnumeration {
  type NumberType = Value
  val One, Two = Value
}

// MyTable.scala
class MyTable(tag: Tag) extends Table[(Int, ColourType, NumberType)](tag, "MYTABLE") {
  def identifier: Rep[Int] = column[Int]("IDENTIFIER", O.PrimaryKey, O.AutoInc)
  def colour: Rep[ColourType] = column[ColourType]("COLOUR")
  def number: Rep[NumberType] = column[NumberType]("NUMBER")
  def * = (identifier, colour, number)
}

要将枚举存储为整数而不是字符串,如@prakhunov 所示,请使用以下命令:

abstract class DatabaseEnumeration extends Enumeration {
  implicit val enumerationMapper = MappedColumnType.base[Value, Int](_.id, this.apply)
}
于 2021-09-23T01:11:48.577 回答