Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to persist enum value in slick

Tags:

scala

slick

I have the follow enum:

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

I need to persist the value of the enum "A", but when the sql is generated the result is 0. this is the table mapping:

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

how to persiste the enum value?

I implemented

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)

but result in:

[error] c.Login - Invalid value for type int : A
like image 970
Longo Avatar asked Oct 09 '13 13:10

Longo


3 Answers

I would personally suggest making your own class inherit from Scala's Enumeration class because then you don't have to create mappers for every single enum you end up using:

Here is the slick 2.0 code that I am currently using:

abstract class DBEnum extends Enumeration {

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

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

This should also work in slick 1.0 ( I have not tested it ):

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

Now all you need for your enums is just to inherit from DBEnum and it should cut down on a lot of boiler plate.

Edit the code accordingly if you want to use string values instead of Ints.

like image 135
prakhunov Avatar answered Nov 15 '22 04:11

prakhunov


Maybe you could create a TypeMapper for your enum type:

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

then you need to reference your column as:

columnLoginStatus.Value

This way it will be transformed back to your enum, when you load data from the database. If you insist on storing your values as characters in the DB, you just need to create a mapper that maps to a char and define your

like image 21
Daniel B. Avatar answered Nov 15 '22 05:11

Daniel B.


After some help I found the solution, the enum:

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

and the table mapping:

    import constants.LoginStatus._
...
    def stLogin = column[LoginStatus]("stlogin", O.NotNull, O.DBType("character(1)"))
like image 2
Longo Avatar answered Nov 15 '22 04:11

Longo