Получение почти удвоенной длины при чтении байта [] из postgres с помощью jpa

У меня есть класс Image, который имеет байт [] для хранения фактических данных изображения. Я могу загрузить и вставить изображение просто отлично в моем веб-приложении. Когда я пытаюсь отобразить изображение после чтения его из JPA, длина моего байта [] всегда равна 2x-1 или 2x-2, где x - длина поля bytea в postgres 9. Очевидно, что браузер не будет отображаться изображение говорит, что оно повреждено. Я мог бы использовать некоторую помощь, чтобы выяснить, почему я получаю (примерно) вдвое больше, чем я ожидаю. Вот отображение моего класса изображения. Используя eclipselink с JPA 2, нажмите Postgres 9 на Mac.

Когда я выбираю из базы данных с

select *, length(bytes) from image;

Я получаю длину 9765. В точке останова моего контроллера длина байта [] равна 19529, что на один байт вдвое больше, чем в базе данных.

@Entity
@Table( name = "image" )
@SequenceGenerator( name = "IMAGE_SEQ_GEN", sequenceName = "IMAGE_SEQUENCE" )
public class Image
        extends DataObjectAbstract<Long>
{
    @Id
    @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "IMAGE_SEQ_GEN" )
    private Long key;

    @Column( name="content_type" )
    private String contentType;

    @Lob
    @Basic( optional=false )
    @Column( name="bytes" )
    private byte[] bytes;

    // constructor and getters and setters

}

pgadmin показывает мне следующее для таблицы изображений

CREATE TABLE image
(
  "key" bigint NOT NULL,
  bytes bytea,
  content_type character varying(255),
  "version" integer,
  CONSTRAINT image_pkey PRIMARY KEY (key)
)
WITH (
  OIDS=FALSE
);

5 ответов

Решение

В PostgreSQL 9 byte[] отправляется клиенту с использованием шестнадцатеричной кодировки.

Если это является причиной ошибки, вы должны найти обновление для JPA. Или вы можете изменить конфигурацию сервера БД, но предыдущий лучше.

"Bytea_output = escape" - это просто обходной путь, Postgres 8.0 изменил кодировку bytea на hex.

Используйте текущий драйвер JDBC начиная с 9.0-dev800 (9.0 Build 801 обновлен в настоящее время), и проблема будет решена.

Дополнительный ответ для пользователей GlassFish 3.x (принципы могут применяться к другим серверам приложений)

Вы можете случайно использовать старый драйвер PostgreSQL JDBC. Вы можете проверить это, введя DataSource где-то (например, EJB) и выполняем на нем следующее:

System.out.println(ds.getConnection().getMetaData().getDriverVersion());

В моем случае это был 8.3, что было неожиданно, поскольку я развертывал с драйверами 9.1.

Чтобы выяснить, откуда это происходит:

System.out.println(Class.forName("org.postgresql.Driver").getProtectionDomain().getCodeSource().getLocation());

Как оказалось для меня, это было в каталоге lib моего домена GlassFish. Я не уверен, как он туда попал - GlassFish, конечно, не доставляет таким образом - поэтому я просто удалил его, и проблема ушла.

Проверьте, есть ли у вас старая банка postgresql. Я столкнулся с той же проблемой и обнаружил в своей библиотеке и jar-файл 8.3 postgresql, и jar-файл 9.1 postgresql. После удаления 8.3 postgresql, byte[] работает нормально.

Попробуйте посмотреть на данные, которые вы получаете. Это может дать вам ключ к пониманию того, что происходит.

Другие вопросы по тегам