У меня есть приложение, использующее аннотации hibernate 3.1 и JPA. Он имеет несколько объектов с байтовыми атрибутами (размером 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, он использует тип postgresql типа bytea (который работает, но только для 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 []?
- Исправлено ли это в какой-то новой версии спящего режима?
Update: После прочтения этого блога Я, наконец, выяснил, каково было обходное решение проблемы JIRA: очевидно, вы должны отказаться от @Lob и аннотировать свойство как:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Однако это не работает для меня - я все равно получаю OID вместо bytea; он, однако, работал для автора проблемы JIRA, который, казалось, хотел бы получить.
После ответа от A. Garcia я попробовал эту комбо, которая на самом деле работает на postgresql, но не на оракуле.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
То, что мне действительно нужно сделать, - это контролировать, что @org.hibernate.annotations.Type комбинация (@Lob + byte [] получает сопоставление) до (на postgresql).
Вот фрагмент из 3.5.5.Final из MaterializedBlobType (sql type Blob). Согласно блогу Стива, postgresql хочет, чтобы вы использовали Streams for bytea (не спрашивайте меня почему) и пользовательский тип BLOB postgresql для oids. Также обратите внимание, что использование setBytes() в JDBC также для байта (из прошлого опыта). Таким образом, это объясняет, почему использование потоков не влияет на то, что оба они предполагают "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 [])? Это работает, UNTIL вы пытаетесь сохранить нулевой байт []. Что думает драйвер 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 и NOT MaterializedBlobType). Я никогда фактически не использовал Blobs с postgresql, но я знаю, что bytea просто работает как один/я ожидаю.
В настоящее время я смотрю на BatchUpdateException - возможно, что драйвер не поддерживает пакетную обработку.
Отличная цитата из 2004: "Подводя итоги, я бы сказал, что мы должны дождаться, когда драйвер JDBC правильно выполнит LOB, прежде чем сменить 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/