Ошибка Scala Anorm Postgresql при сохранении байтового массива
У меня есть таблица базы данных в Scala Playframework, определенная как
CREATE TABLE account (
id SERIAL,
email TEXT NOT NULL,
buffer BYTEA NOT NULL,
PRIMARY KEY (id)
);
Я использую буфер протокола для сериализации объекта в байтовый массив со следующим кодом
DB.withConnection{ implicit c=>
SQL("INSERT INTO device (buffer,secret) VALUES ({secret},{buffer})").on(
"secret"->device.getSecret(),
"buffer"->device.toByteArray()
).executeInsert()
}
Тип, возвращаемый device.toByteArray()
является Array[Byte]
который должен соответствовать типу базы данных для этого столбца. Однако после выполнения кода я получаю
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 ответ
Решение
Глядя на источник anorm и документы Postgres, кажется, что вам нужно добавить обработчик для хранения Array[Byte]
правильно используя setBytes
вместо setObject
, который требует текущий код.
Я бы расширил соответствие в любом параметре в рамках, чтобы прочитать
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)
// ...
и добавить
implicit val byteArrayToStatement = new ToStatement[Array[Byte]] {
def set(s: java.sql.PreparedStatement, index: Int, aValue: Array[Byte]): Unit = setAny(index, aValue, s)
}
Потенциально вы должны быть в состоянии сделать это и вне фреймворка, используя магию классов типов, но у меня нет времени, чтобы понять это прямо сейчас.