правильная аннотация гибернации для байта []

У меня есть приложение, использующее аннотации 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 тип 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 года: Я пытаюсь показать состояние инвентаря для деталей (для наших продуктов), и этот запрос становится сложным, только если я попытаюсь вернуть все детали. Позвольте мне ...

Я пытаюсь осмыслить это сегодня утром.

Я пытаюсь показать инвентарный статус для деталей (для наших продуктов), и этот запрос только усложняется если я попытаюсь вернуть все части.

Позвольте мне изложить это:

  • single table inventoryReport
  • У меня есть отдельный список X частей, которые я хочу отобразить, результат должен быть X # строк (1 строка на каждую часть, показывающую последнюю запись инвентаря).
  • таблица состоит из датированных записей изменений инвентаризации (поэтому мне нужна только последняя запись даты для каждой части).
  • все данные содержится в этой единой таблице, поэтому соединения не требуются.

В настоящее время для 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 строк.

Мысли? Я застрял ...

5
задан Jakub 9 September 2010 в 14:11
поделиться