У меня есть приложение, использующее аннотации 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), который переносится между основными базами данных.
Обновить : Прочитав этот блог , я, наконец, понял, каков был исходный обходной путь в проблеме 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 тип Blob). Согласно блогу Стива, postgresql хочет, чтобы вы использовали Streams для bytea (не спрашивайте меня, почему) и postgresql ' s настраиваемый тип Blob для 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 года: Я пытаюсь показать состояние инвентаря для деталей (для наших продуктов), и этот запрос становится сложным, только если я попытаюсь вернуть все детали. Позвольте мне ...
Я пытаюсь осмыслить это сегодня утром.
Я пытаюсь показать инвентарный статус
для деталей (для наших продуктов), и этот запрос только усложняется если я попытаюсь вернуть все части.
Позвольте мне изложить это:
inventoryReport
последняя
запись даты для каждой части). В настоящее время для 1 отдельной части, это довольно просто, и я могу добиться этого, выполнив следующий sql (чтобы дать вам некоторое представление):
SELECT TOP (1) ldDate, ptProdLine, inPart, inSite, inAbc, ptUm, inQtyOh + inQtyNonet AS in_qty_oh, inQtyAvail, inQtyNonet, ldCustConsignQty, inSuppConsignQty
FROM inventoryReport
WHERE (ldPart = 'ABC123')
ORDER BY ldDate DESC
, который дает мне мою первую строку TOP 1, так просто для каждой части, однако мне нужно показать все X (скажем, 30 частей ). Итак, мне нужно 30 строк с таким результатом. Конечно, простым решением было бы зациклить X # вызовов sql в моем коде (но это было бы дорого), и этого было бы достаточно, но для этой цели я хотел бы еще немного поработать этот SQL, чтобы уменьшить количество вызовов x # обратно в db (если не требуется) до 1 запроса.
Из того, что я вижу здесь, мне нужно каким-то образом отслеживать последнюю дату для каждого элемента, пока ищу свой набор результатов.
В конечном итоге я бы выполнил
WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc)
чтобы ограничить количество необходимых мне частей. Надеюсь, я достаточно ясно сформулировал свой вопрос. Дайте мне знать, если у вас есть идея. Я не могу выполнить DISTINCT
, поскольку строки не совпадают, дата должна быть последней, а мне нужно максимум X строк.
Мысли? Я застрял ...