У меня есть приложение, использующее аннотации hibernate 3.1 и JPA.Он имеет несколько объектов с атрибутами byte [] (размером от 1 до 200 КБ).Он использует аннотацию 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 []?
- Исправлено ли это в какой-то недавней версии hibernate?
Обновление: После прочтения этого блога Я наконец-то выяснил, какой оригинальный обходной путь в JIRAпроблема заключалась в следующем: очевидно, вы должны отбросить @Lob и аннотировать свойство следующим образом:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Однако это не работает для меня - я все еще получаю OID вместо bytea;однако это сработало для автора проблемы JIRA, который, похоже, хотел oid.
После ответа от A. Garcia я попробовал эту комбинацию, которая на самом деле работает на postgresql, но не на oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
Что мне действительно нужно сделать, так это указать, какой @ org.hibernate.annotations.Type комбинации (@Lob + byte [] сопоставляется) с (на postgresql).
Вот фрагмент из 3.5.5. Финал из MaterializedBlobType (тип Blob sql).Согласно блогу Стива, postgresql хочет, чтобы вы использовали Streams для bytea (не спрашивайте меня, почему) и пользовательский тип Blob для og.Также обратите внимание, что использование 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
Система типов в hibernate в настоящее время находится в процессе разработки (согласно комментарию об устаревании 3.5.5).На самом деле, большая часть кода 3.5.5 устарела, трудно понять, на что обращать внимание при создании подкласса PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' в postgresql должны быть сопоставлены с некоторым пользовательским типом, который использует доступ к JDBC в стиле OID (т. Е. Объект PostgresqlBlobType и NOT MaterializedBlobType).На самом деле я никогда не использовал успешно BLOB-объектов с postgresql, но я знаю, что bytea просто работает так, как я ожидал.
В настоящее время я смотрю на исключение BatchUpdateException - возможно, драйвер этого не делаетподдержка дозирования.
Великолепная цитата 2004 года: «Подводя итог моим разговорам, я бы сказал, что нам следует подождать, пока драйвер JDBC правильно выполнит большие объекты, прежде чем менять Hibernate».
Ссылки: