У меня есть приложение, использующее аннотации hibernate 3.1 и JPA. В нем есть несколько объектов с атрибутами byte [] (размером от 1k до 200k). Он использует аннотацию JPA @Lob, и hibernate 3.1 может нормально читать их во всех основных базах данных - похоже, он скрывает особенности поставщика JDBC Blob (как и должно быть).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Нам пришлось перейти на 3.5, когда мы обнаружили, что hibernate 3.5 нарушает (и не исправляет) эту комбинацию аннотаций в postgresql (без обходного пути). Я пока не нашел четкого исправления, но заметил, что если я просто удалю @Lob, он будет использовать bytea типа postgresql (который работает, но только на postgres).
annotation postgres oracle works on
-------------------------------------------------------------
byte[] + @Lob oid blob oracle
byte[] bytea raw(255) postgresql
byte[] + @Type(PBA) oid blob oracle
byte[] + @Type(BT) bytea blob postgresql
once you use @Type, @Lob seems to not be relevant
note: oracle seems to have deprecated the "raw" type since 8i.
Я ищу способ иметь один аннотированный класс (со свойством blob), который можно переносить в основные базы данных.
- Каков переносимый способ аннотировать свойство byte []?
- Исправлено ли это в какой-нибудь последней версии гибернации?
Обновление: после прочтения этого блога я, наконец, понял, каким было исходное решение проблемы JIRA: по-видимому, вы должны удалить @Lob и аннотировать свойство как:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Однако у меня это не работает - я все равно получаю OID вместо bytea; Тем не менее, это сработало для автора проблемы JIRA, который, похоже, захотел oid.
После ответа А. Гарсиа я попробовал эту комбинацию, которая действительно работает на postgresql, но не на oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
Что мне действительно нужно сделать, так это контролировать, какие @ org.hibernate.annotations. Введите комбинацию (@Lob + byte [] будет отображена) на (в postgresql).
Вот фрагмент из 3.5.5.Final из MaterializedBlobType (sql type Blob). Согласно блогу Стива, postgresql хочет, чтобы вы использовали Streams для bytea (не спрашивайте меня, почему) и пользовательский тип Blob postgresql для oids. Также обратите внимание, что использование setBytes () в JDBC также предназначено для bytea (из прошлого опыта). Итак, это объясняет, почему потоки использования не влияют на них, они оба принимают «bytea».
public void set(PreparedStatement st, Object value, int index) {
byte[] internalValue = toInternalFormat( value );
if ( Environment.useStreamsForBinary() ) {
// use streams = true
st.setBinaryStream( index,
new ByteArrayInputStream( internalValue ), internalValue.length );
}
else {
// use streams = false
st.setBytes( index, internalValue );
}
}
Это приводит к:
ERROR: column "signature" is of type oid but expression is of type bytea
Обновление Следующий логичный вопрос: «Почему бы просто не изменить определения таблиц вручную на bytea» и сохранить (@Lob + byte [])? Это делает работу, ПОКА вы пытаетесь сохранить нулевые байты []. Драйвер postgreSQL считает, что это выражение типа OID, а тип столбца - bytea - это потому, что hibernate (правильно) вызывает JDBC.setNull () вместо JDBC.setBytes (null), который ожидает драйвер PG.
ERROR: column "signature" is of type bytea but expression is of type oid
Система типов в спящем режиме в настоящее время находится в стадии разработки (согласно устаревшему комментарию 3.5.5). Фактически, так много кода 3.5.5 устарело, трудно понять, на что обращать внимание при подклассе PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' в postgresql должны быть сопоставлены с некоторым настраиваемым типом, который использует доступ JDBC в стиле OID (например, объект PostgresqlBlobType и НЕ MaterializedBlobType). Я никогда успешно не использовал Blobs с postgresql, но я знаю, что bytea просто работает так, как я ожидал.
В настоящее время я смотрю на исключение BatchUpdateException - возможно, драйвер не поддерживает пакетную обработку.
Замечательная цитата из 2004 года: «Подводя итог своим рассуждениям, я бы сказал, что нам следует дождаться, пока драйвер JDBC будет правильно выполнять большие объекты, прежде чем менять Hibernate».
Ссылки:
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/
Ответы:
Все зависит от того, чего вы хотите. JPA может сохранять не аннотированный
byte[]
. Из спецификации JPA 2.0:И Hibernate отобразит его «по умолчанию» на SQL
VARBINARY
(или SQL, вLONGVARBINARY
зависимости отColumn
размера?), Который PostgreSQL обрабатывает с расширениемbytea
.Но если вы хотите,
byte[]
чтобы файл хранился в большом объекте, вам следует использовать файл@Lob
. Из спецификации:И Hibernate отобразит его на SQL,
BLOB
который PostgreSQL обрабатывает с расширениемoid
.Что ж, проблема в том, что я не знаю, в чем именно проблема. Но я могу по крайней мере сказать, что ничего не изменилось с версии 3.5.0-Beta-2 (в которую были внесены изменения) в ветке 3.5.x.
Но мое понимание проблем , как HHH-4876 , HHH-4617 и в PostgreSQL и BLOB - (упоминается в Javadoc из
PostgreSQLDialect
) является то , что вы должны установить следующее свойствоесли вы хотите использовать
oid
то естьbyte[]
с@Lob
(это я понимаю, посколькуVARBINARY
это не то, что вы хотите с Oracle). Вы пробовали это?В качестве альтернативы HHH-4876 предлагает использовать устаревшее,
PrimitiveByteArrayBlobType
чтобы получить старое поведение (до Hibernate 3.5).Ссылки
Ресурсы
источник
hibernate.jdbc.use_streams_for_binary=false
тоже? (сейчас проверю, что сказал Стив).Вот что говорит Oreilly Enterprise JavaBeans, 3.0.
Вот исходный код PostgreSQLDialect
Так что ты можешь сделать
Переопределите PostgreSQLDialect следующим образом
Теперь просто определите свой собственный диалект
И используйте свою портативную аннотацию JPA @Lob
ОБНОВИТЬ
Здесь было добыто здесь
...
что можно объяснить здесь
...
Интересно, потому что когда он отображает Types.BOLB как bytea (см. CustomPostgreSQLDialect), он получает
при вставке или обновлении
источник
Я использую Hibernate 4.2.7.SP1 с Postgres 9.3, и у меня следующие работы:
поскольку у Oracle нет проблем с этим, а для Postgres я использую собственный диалект:
Преимущество этого решения, которое я считаю, состоит в том, что я могу не трогать банки спящего режима.
Дополнительные сведения о проблемах совместимости Postgres / Oracle с Hibernate см. В моем сообщении в блоге .
источник
Наконец-то у меня это работает. Он расширяет решение от А. Гарсиа, однако, поскольку проблема заключается в типе гибернации Тип MaterializedBlob, просто сопоставление Blob> bytea недостаточно, нам нужна замена для MaterializedBlobType, который работает с поддержкой сломанных BLOB-объектов в гибернации. Эта реализация работает только с bytea, но, возможно, парень из проблемы JIRA, которому нужен OID, мог бы внести свой вклад в реализацию OID.
К сожалению, замена этих типов во время выполнения - это боль, поскольку они должны быть частью диалекта. Если бы только это расширение JIRA попало в 3.6, это было бы возможно.
Большая часть этого, вероятно, может быть статической (действительно ли getBinder () нужен новый экземпляр?), Но я действительно не понимаю внутреннего спящего режима, поэтому это в основном копирование + вставка + изменение.
источник
Я исправил свою проблему, добавив аннотацию @Lob, которая создаст byte [] в oracle как blob, но эта аннотация создаст поле как oid, которое не работает должным образом. Чтобы сделать byte [] созданным как bytea, я сделал клиентский диалект для postgres, как показано ниже
Также необходимо переопределить параметр для диалекта
spring.jpa.properties.hibernate.dialect = com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
больше подсказок можно найти по ней: https://dzone.com/articles/postgres-and-oracle
источник
Я получил это, переопределив аннотацию с файлом XML для Postgres. Аннотация сохраняется для Oracle. На мой взгляд, в этом случае было бы лучше переопределить отображение этой проблемы с отображением xml. Мы можем переопределить один / несколько объектов с помощью сопоставления xml. Таким образом, мы будем использовать аннотацию для нашей базы данных, которая в основном поддерживается, и файл xml для каждой другой базы данных.
Примечание: нам просто нужно переопределить один единственный класс, так что это не имеет большого значения. Подробнее читайте в моем примере Пример переопределения аннотации с помощью XML
источник
В Postgres @Lob ломается для byte [], поскольку он пытается сохранить его как oid, и для String также возникает такая же проблема. Ниже код ломается на postgres, который отлично работает с oracle.
и
Чтобы исправить выше, на postgres ниже написано custom hibernate.dialect
Теперь настройте собственный диалект в спящем режиме
XYZ - это имя пакета.
Теперь он работает нормально. ПРИМЕЧАНИЕ. Моя версия Hibernate - 5.2.8. Окончательная версия Postgres - 9.6.3.
источник
Спасибо Джастину, Паскаль за то, что направил меня в правильном направлении. Я также столкнулся с той же проблемой с Hibernate 3.5.3. Ваши исследования и указатели на нужные классы помогли мне определить проблему и исправить.
Для тех, кто все еще придерживается Hibernate 3.5 и использует комбинацию oid + byte [] + @LoB, вот что я сделал, чтобы исправить эту проблему.
Я создал собственный BlobType, расширяющий MaterializedBlobType и переопределяющий методы set и get с доступом в стиле oid.
Зарегистрируйте CustomBlobType в Hibernate. Вот что я сделал для этого.
источник