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

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

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

select *, length(bytes) from image;

Я получаю длину 9765. В точке останова в моем контроллере длина byte[] равна 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
);

person digitaljoel    schedule 30.05.2011    source источник


Ответы (5)


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

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

person jordani    schedule 30.05.2011
comment
интересно, что я не делал никаких настроек, и он работает, если я запускаю сервер в Windows, но не в Mac. Есть мысли по этому поводу? - person digitaljoel; 31.05.2011
comment
Это может быть так же просто, как убедиться, что: bytea_output = escape присутствует в postgresql.conf Я скоро прочитал это и надеюсь, что это может вам помочь. Есть ли Postgre в Windows v. 9 или более ранней версии? - person jordani; 31.05.2011
comment
Я не особо смотрел на конфигурацию в окне Windows, но вернулся к своему Mac и установил свойство, и все выглядит хорошо. Я ценю помощь?! - person digitaljoel; 31.05.2011
comment
Как и предложил @jordani, драйвер JDBC обрабатывает BYTEA[] как TEXT, даже если на сервере тип данных BYTEA[]. Правильное декодирование шестнадцатеричных значений в двоичное значение должно решить проблему (слишком распространенная проблема с некоторыми драйверами). - person Sean; 01.06.2011

«bytea_output = escape» — это просто обходной путь, Postgres 8.0 изменил кодировку bytea на шестнадцатеричную.

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

person samy-delux    schedule 12.07.2011
comment
Это предложение и другие - просто дикие удары в темноте. В моем случае работал сервер 9.0 с драйверами JDBC 9.0. У сервера 9.1 с драйверами JDBC 9.1 есть эта проблема. - person Distortum; 15.01.2012
comment
Спасатель жизни. Большое спасибо за ответ! - person jmpenetra; 08.06.2013

Дополнительный ответ для пользователей 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 определенно не поставляется таким образом — поэтому я просто удалил его, и проблема исчезла.

person Distortum    schedule 15.01.2012

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

person MRAB    schedule 30.05.2011

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

person Jiong    schedule 29.12.2015