Scala Anorm Postgresql Error When Storing Byte Array

六眼飞鱼酱① 提交于 2019-12-12 16:06:53

问题


I have a database table in Scala Playframework defined as

CREATE TABLE account (
    id     SERIAL,
    email  TEXT  NOT NULL,
    buffer BYTEA NOT NULL,
    PRIMARY KEY (id)
);

I am using a protocol buffer to serialize an object to a byte array with the following code

DB.withConnection{ implicit c=>
  SQL("INSERT INTO device (buffer,secret) VALUES ({secret},{buffer})").on(
    "secret"->device.getSecret(),
    "buffer"->device.toByteArray()
  ).executeInsert()
}

The type returned by device.toByteArray() is Array[Byte] which should match the database type for that column. However upon executing the code I get

play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[PSQLException: ERROR: column "buffer" is of type bytea but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.
  Position: 44]]
    at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:134) [play_2.9.1.jar:2.0.3]
    at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115) [play_2.9.1.jar:2.0.3]
    at akka.actor.Actor$class.apply(Actor.scala:318) [akka-actor.jar:2.0.2]
    at play.core.ActionInvoker.apply(Invoker.scala:113) [play_2.9.1.jar:2.0.3]
    at akka.actor.ActorCell.invoke(ActorCell.scala:626) [akka-actor.jar:2.0.2]
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:197) [akka-actor.jar:2.0.2]
Caused by: org.postgresql.util.PSQLException: ERROR: column "buffer" is of type bytea but expression is of type character varying

回答1:


Looking at the anorm source and the Postgres docs, it looks like you'll need to add a handler for storing Array[Byte] properly using setBytes instead of setObject, which the current code calls for.

I'd extend the match in anyParameter in the framework to read

    value match {
      case Some(bd: java.math.BigDecimal) => stmt.setBigDecimal(index, bd)
      case Some(b: Array[Byte]) => stmt.setBytes(index, b)
      case Some(o) => stmt.setObject(index, o)
      // ...

and add

implicit val byteArrayToStatement = new ToStatement[Array[Byte]] {
  def set(s: java.sql.PreparedStatement, index: Int, aValue: Array[Byte]): Unit = setAny(index, aValue, s)
}

You should potentially be able to do this outside the framework as well through the type class magic at work here, but I don't have time to figure that out right now.



来源:https://stackoverflow.com/questions/12001114/scala-anorm-postgresql-error-when-storing-byte-array

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