How to map postgresql custom enum column with Slick2.0.1?

橙三吉。 提交于 2021-02-19 02:57:05

问题


I just can't figure it out. What I am using right now is:

abstract class DBEnumString extends Enumeration {
  implicit val enumMapper = MappedJdbcType.base[Value, String](
     _.toString(),
     s => this.withName(s)
  )
}

And then:

object SomeEnum extends DBEnumString {
  type T = Value
  val A1 = Value("A1")
  val A2 = Value("A2")
}

The problem is, during insert/update JDBC driver for PostgreSQL complains about parameter type being "character varying" when column type is "some_enum", which is reasonable as I am converting SomeEnum to String.

How do I tell Slick to treat String as DB-defined "enum_type"? Or how to define some other Scala-type that will map to "enum_type"?


回答1:


I had similar confusion when trying to get my postgreSQL enums to work with slick. Slick-pg allows you to use Scala enums with your databases enums, and the test suite shows how.

Below is an example.

Say we have this enumerated type in our database.

CREATE TYPE Dog AS ENUM ('Poodle', 'Labrador');

We want to be able to map these to Scala enums, so we can use them happily with Slick. We can do this with slick-pg, an extension for slick.

First off, we make a Scala version of the above enum.

object Dogs extends Enumeration {
  type Dog = Value
  val Poodle, Labrador = Value
}

To get the extra functionality from slick-pg we extend the normal PostgresDriver and say we want to map our Scala enum to the PostgreSQL one (remember to change the slick driver in application.conf to the one you've created).

object MyPostgresDriver extends PostgresDriver with PgEnumSupport {
  override val api = new API with MyEnumImplicits {}

  trait MyEnumImplicits {
    implicit val dogTypeMapper = createEnumJdbcType("Dog", Dogs)
    implicit val dogListTypeMapper = createEnumListJdbcType("Dog", Dogs)

    implicit val dogColumnExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder(Dogs)
    implicit val dogOptionColumnExtensionMethodsBuilder = createEnumOptionColumnExtensionMethodsBuilder(Dogs)
  }
}

Now when you want to make a new model case class, simply use the corresponding Scala enum.

case class User(favouriteDog: Dog) 

And when you do the whole DAO table shenanigans, again you can just use it.

class Users(tag: Tag) extends Table[User](tag, "User") {
  def favouriteDog = column[Dog]("favouriteDog")
  def * = (favouriteDog) <> (Dog.tupled, Dog.unapply _)
}

Obviously you need the Scala Dog enum in scope wherever you use it.

Due to a bug in slick, currently you can't dynamically link to a custom slick driver in application.conf (it should work). This means you either need to run play framework with start and not get dynamic recompiling, or you can create a standalone sbt project with just the custom slick driver in it and depend on it locally.



来源:https://stackoverflow.com/questions/22945485/how-to-map-postgresql-custom-enum-column-with-slick2-0-1

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