Как мне преобразовать java.util.UUID в doobie.syntax.SqlInterpolator.Одиночный фрагмент?

#scala #circe #http4s #doobie

#scala #circe #http4s #doobie

Вопрос:

Я пытаюсь настроить простое приложение scala с базой данных, используя doobie, http4s и circe.

Как мне преобразовать java.util.UUID в doobie.syntax.SqlInterpolator.Одиночный фрагмент?

 final case class User(id: UUID, details: UserDetails)
  
   implicit val userDecoder: Decoder[User] = deriveDecoder[User]
  implicit def userEntityDecoder[F[_]: Sync]: EntityDecoder[F, User] = jsonOf

  implicit val userEncoder: Encoder[User] = deriveEncoder[User]
  implicit def userEntityEncoder[F[_]: Applicative]: EntityEncoder[F, User] = jsonEncoderOf

  implicit val put: Put[User] =
    Put[Json].contramap(_.asJson)

  implicit val get: Get[User] =
    Get[Json].temap(_.as[User].left.map(_.show))

  
 [info] welcome to sbt 1.3.12 (N/A Java 14.0.1)
[info] loading global plugins from /Users/ryan/.sbt/1.0/plugins
[info] loading settings for project bobbymoore-build from plugins.sbt ...
[info] loading project definition from /Users/ryan/fullStackRyan/bobbymoore/project
[info] loading settings for project root from build.sbt ...
[info] set current project to bobbymoore (in build file:/Users/ryan/fullStackRyan/bobbymoore/)
[info] sbt server started at local:///Users/ryan/.sbt/1.0/server/90f560b1e0964865fc4c/sock
sbt:bobbymoore> compile
[info] Compiling 1 Scala source to /Users/ryan/fullStackRyan/bobbymoore/target/scala-2.13/classes ...
[error] /Users/ryan/fullStackRyan/bobbymoore/src/main/scala/com/c/bobbymoore/database/UserQueries.scala:24:20: type mismatch;
[error]  found   : java.util.UUID
[error]  required: doobie.syntax.SqlInterpolator.SingleFragment
[error]          |  ${user.id},
[error]                    ^
[error] /Users/ryan/fullStackRyan/bobbymoore/src/main/scala/com/c/bobbymoore/database/UserQueries.scala:34:21: type mismatch;
[error]  found   : java.util.UUID
[error]  required: doobie.syntax.SqlInterpolator.SingleFragment
[error]          |WHERE id=$id
[error]                     ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 2 s, completed 13 Oct 2020, 16:31:46

  

Ответ №1:

Если вы используете PostgreSQL, а UUID в Java преобразуется в столбец UUID в таблице Postgres, тогда вам нужно использовать расширения Postgres для Doobie

 // other doobie imports
import doobie.postgres._
import doobie.postgres.implicits._

sql"""SELECT id, name FROM users WHERE id = ${user.id}""".query[(UUID, String)]
  

Если вы не используете PSQL, и этот UUID отображается в ТЕКСТОВОЕ поле, вам нужно либо сопоставить это самостоятельно в запросе:

 sql"""SELECT id, name FROM users WHERE id = ${user.id.toString}"""
  .query[(String, String)]
  .map { case (uuid, name) => (UUID.fromString(uuid), name) }
  

или определите свой собственный Meta[UUID] экземпляр, например

 implicit val uuidMeta: Meta[UUID] =
  Meta[String].imap[UUID](UUID.fromString)(_.toString)
  

Это необходимо, если вы хотите получить экземпляр, например, для класса case, который содержит UUID. Библиотека расширений Postgres предоставляет тот, который соответствует реализации PSQL.

Вам обязательно нужно определить свой собственный экземпляр Meta, если вы используете, например Array[Byte] , или какое-либо другое числовое представление на стороне DB для представления UUID.