在Play(jdbc)中无法处理UUID

时间:2013-12-31 07:49:56

标签: scala jdbc postgresql-9.2 playframework-2.2 anorm

我在Play项目中使用joda DateTimeUUID。我正在努力尝试从Postgresql获取它们:

import org.joda.time.DateTime
case class MyClass(id: Pk[UUID], name: String, addedAt: DateTime)

object MyClass {
  val simple =
    SqlParser.get[Pk[UUID]]("id") ~
    SqlParser.get[String]("name") ~
    SqlParser.get[DateTime]("added_at") map {
      case id ~ name ~ addedAt => MyClass(id, name, addedAt)
    }

  implicit def rowToId = Column.nonNull[UUID] { (value, meta) => 
    maybeValueToUUID(value) match {
      case Some(uuid) => Right(uuid)
      case _ => Left(TypeDoesNotMatch( s"Cannot convert $value: ${value.asInstanceOf[Any].getClass} to UUID"))
    }
  }

  implicit def idToStatement = new ToStatement[UUID] {
    def set(s: PreparedStatement, index: Int, aValue: UUID): Unit = s setObject(index, toByteArray(aValue))
  }

 def getSingle(id: UUID): Option[MyClass] = {
  DB withConnection {
    implicit con =>
      SQL("SELECT my_table.id, my_table.name, my_table.added_at FROM my_table WHERE id = {id}")
        .on('id -> id)
        .as(MyClass.simple.*)
  } match {
    case List(x) => Some(x)
    case _ => None
  }
}

joda DateTime的隐含函数被省略,因为它们此时不会导致任何错误。导致错误的原因是getSingle(...) - 从UUID转换为org.postgresql.util.PSQLException: operator does not exist: uuid = bytea Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts. 。错误是

  private def maybeValueToUUID(value: Any): Option[UUID] = maybeValueToByteArray(value) match {
    case Some(bytes) => Some(fromByteArray(bytes))
    case _ => None
  }

  private def maybeValueToByteArray(value: Any): Option[Array[Byte]] =
    try {
      value match {
        case bytes: Array[Byte] => Some(bytes)
        case clob: Clob => None //todo
        case blob: Blob => None //todo
        case _ => None
      }
    } catch {
      case e: Exception => None
  }

  def toByteArray(uuid: UUID) = {
    val buffer = ByteBuffer.wrap(new Array[Byte](16))
    buffer putLong uuid.getMostSignificantBits
    buffer putLong uuid.getLeastSignificantBits
    buffer.array
  }

  def fromByteArray(b: Array[Byte]) = {
    val buffer = ByteBuffer.wrap(b)
    val high = buffer.getLong
    val low = buffer.getLong
    new UUID(high, low)
  }

4个辅助函数:

{{1}}

请注意,我正在尝试检索的记录存在且格式正确。

0 个答案:

没有答案