Как сохранить значение перечисления в slick

У меня есть следующее перечисление:

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

person Longo    schedule 09.10.2013    source источник
comment
это несколько связано « title = «как я могу создать собственный тип столбца с безопасным шрифтом в scala»> stackoverflow.com/questions/19030875/   -  person cvogt    schedule 12.10.2013
comment
Это также обсуждается в списке рассылки Slick groups.google.com/d. /msg/scalaquery/Cd5iG-tJchM/fEIhq8IPVJQJ   -  person cvogt    schedule 13.10.2013
comment
также связано с stackoverflow.com/ вопросы/18752929/   -  person cvogt    schedule 13.10.2013


Ответы (3)


Я бы лично предложил сделать ваш собственный класс унаследованным от класса Enumeration Scala, потому что тогда вам не нужно создавать преобразователи для каждого отдельного перечисления, которое вы в конечном итоге используете:

Вот гладкий код 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)
}

Это также должно работать в версии 1.0 (я не проверял):

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

Теперь все, что вам нужно для ваших перечислений, это просто наследовать от DBEnum, и это должно сократить много шаблонов.

Отредактируйте код соответствующим образом, если вы хотите использовать строковые значения вместо Ints.

person prakhunov    schedule 16.10.2013
comment
tks @prakhunov, я отредактировал ваш ответ, добавив код, который я изменил для работы со строками. - person Longo; 17.10.2013
comment
Обратите внимание, что этот код не работает с текущей версией из-за github.com/slick/ slick/issues/540 . Вы получаете сообщение об ошибке JdbcProfile has no TypeInfo for type scala.slick.driver.JdbcTypesComponent$MappedJdbcType .... Чтобы обойти это, измените импорт на ваш конкретный драйвер базы данных вместо «jdbc». например import scala.slick.driver.HsqldbDriver.simple._ и import scala.slick.driver.HsqldbDriver.MappedJdbcType - person Luciano; 04.02.2014
comment
Вы правы, я заметил это, когда обновлял свой проект до последней гладкой версии 2.0. Изначально у нас были планы по поддержке нескольких баз данных, что, к сожалению, сейчас невозможно. - person prakhunov; 27.02.2014
comment
Если вы предпочитаете черты: trait EnumMapper { this: Enumeration => implicit val enumMapper = MappedColumnType.base[Value, Int](_.id, this.apply) } - person OlivierBlanvillain; 14.03.2014
comment
я не могу пока попробовать, так как я сейчас не на компьютере, но этот ответ все еще действителен для slick 3.1.0? - person pedrorijo91; 16.11.2015

Возможно, вы могли бы создать 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)
  }
 )

тогда вам нужно сослаться на свой столбец как:

столбецLoginStatus.Value

Таким образом, он будет преобразован обратно в ваше перечисление, когда вы загружаете данные из базы данных. Если вы настаиваете на хранении ваших значений в виде символов в БД, вам просто нужно создать преобразователь, который сопоставляется с символом, и определить ваш

person Daniel B.    schedule 09.10.2013

После некоторой помощи я нашел решение, перечисление:

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)"))
person Longo    schedule 10.10.2013