Kamil Duda Kamil Duda - 1 month ago 13
Scala Question

Persist UUID in PostgreSQL using Play Slick - java.sql.BatchUpdateException

I've been playing around with Play and came upon a problem while trying to save some sample data into PostrgeSQL.

I'm aware that I can convert UUID to String and save it that way, but I can't get it to work with UUID.

The error I get:

Error injecting constructor, java.sql.BatchUpdateException: Batch entry 0 insert into "COMPANIES" ("ID","NAME") values (?,'Amazon') was aborted: ERROR: column "ID" is of type uuid but expression is of type bytea

My dependencies:

libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"
libraryDependencies += "com.typesafe.play" %% "play-slick" % "3.0.1"

Company case class:

case class Company(id: UUID = UUID.randomUUID, name: String)

Slick table definition:

val companies: TableQuery[Companies] = TableQuery[Companies]

class Companies(tag: Tag) extends Table[Company](tag, "COMPANIES") {
override def * : ProvenShape[Company] = (id, name) <> (Company.tupled, Company.unapply)

def id: Rep[UUID] = column[UUID]("ID", O.PrimaryKey, O.SqlType("UUID"))
def name: Rep[String] = column[String]("NAME")

In logs I've noticed that UUID gets converted indeed into bytes:

[debug] s.j.J.statement - Preparing statement: insert into "COMPANIES" ("ID","NAME") values (?,?)
[debug] s.j.J.parameter - /-------------+-----------\
[debug] s.j.J.parameter - | 1 | 2 |
[debug] s.j.J.parameter - | Bytes | String |
[debug] s.j.J.parameter - |-------------+-----------|
[debug] s.j.J.parameter - | [B@17c2de51 | Amazon |
[debug] s.j.J.parameter - | [B@6a4e93d5 | Google |
[debug] s.j.J.parameter - | [B@69f81ed7 | Microsoft |
[debug] s.j.J.parameter - \-------------+-----------/

I would really appreciate some help or hints.

Answer Source

You have to import the specific profile for your database system. In your case:

import slick.jdbc.PostgresProfile.api._

Although I would recommend injecting the configuration provider and then import that api. That way your code will work if you configure another database management system.

class DAO @Inject()(@NamedDatabase("DB_NAME_FROM_CONFIG") protected val dbConfigProvider: DatabaseConfigProvider)
                      (implicit ec: ExecutionContext) {
  import profile.api._