właściwa adnotacja hibernacji dla bajtu []

120

Mam aplikację używającą hibernacji 3.1 i adnotacji JPA. Ma kilka obiektów z atrybutami byte [] (o rozmiarze 1k - 200k). Używa adnotacji JPA @Lob, a hibernacja 3.1 może je dobrze odczytać we wszystkich głównych bazach danych - wydaje się, że ukrywa osobliwości dostawcy JDBC Blob (tak jak powinno).

@Entity
public class ConfigAttribute {
  @Lob
  public byte[] getValueBuffer() {
    return m_valueBuffer;
  }
}

Musieliśmy uaktualnić do wersji 3.5, kiedy odkryliśmy, że hibernacja 3.5 przerywa (i nie naprawi) tej kombinacji adnotacji w postgresql (bez obejścia). Jak dotąd nie znalazłem wyraźnej poprawki, ale zauważyłem, że jeśli po prostu usunę @Lob, używa on bajtu typu postgresql (który działa, ale tylko na 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.

Szukam sposobu, aby mieć jedną klasę z adnotacjami (z właściwością blob), która jest przenośna w głównych bazach danych.

  • Jaki jest przenośny sposób dodawania adnotacji do właściwości byte []?
  • Czy zostało to naprawione w jakiejś najnowszej wersji hibernacji?

Aktualizacja: po przeczytaniu tego bloga w końcu odkryłem, jakie było pierwotne obejście problemu z JIRA: Najwyraźniej powinieneś porzucić @Lob i dodać adnotację do właściwości jako:

@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") 
byte[] getValueBuffer() {...

Jednak to nie działa dla mnie - nadal otrzymuję identyfikatory OID zamiast bajtów; to jednak zadziałało dla autora wydania JIRA, który wydawał się chcieć oid.

Po odpowiedzi od A. Garcii, wypróbowałem następnie tę kombinację, która faktycznie działa na postgresql, ale nie na Oracle.

@Type(type="org.hibernate.type.BinaryType") 
byte[] getValueBuffer() {...

To, co naprawdę muszę zrobić, to kontrolować, które @ org.hibernate.annotations.Type kombinację (@Lob + bajt [] zostanie zmapowane) do (na postgresql).


Oto fragment z 3.5.5.Final z MaterializedBlobType (sql type Blob). Według bloga Steve'a, postgresql chce, abyś używał strumieni dla bajtów (nie pytaj mnie dlaczego) i niestandardowego typu Bloba postgresql dla oids. Zauważ również, że użycie setBytes () na JDBC jest również dla bytea (z wcześniejszych doświadczeń). To wyjaśnia, dlaczego strumienie użycia nie mają wpływu, obie przyjmują „bajt”.

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 );
 }
}

To skutkuje:

ERROR: column "signature" is of type oid but expression is of type bytea

Aktualizacja Kolejne logiczne pytanie brzmi: „dlaczego po prostu nie zmienić ręcznie definicji tabeli na bajtowe” i zachować (@Lob + bajt [])? To nie praca, DOPÓKI próbie zapisania null byte []. Który sterownik postgreSQL uważa za wyrażenie typu OID, a typ kolumny to bajt - dzieje się tak, ponieważ hibernacja (słusznie) wywołuje JDBC.setNull () zamiast JDBC.setBytes (null), czego oczekuje sterownik PG.

ERROR: column "signature" is of type bytea but expression is of type oid

System typów w hibernacji jest obecnie w toku (zgodnie z komentarzem do wycofania 3.5.5). W rzeczywistości tak duża część kodu 3.5.5 jest przestarzała, że ​​trudno jest wiedzieć, na co zwrócić uwagę podczas tworzenia podklas PostgreSQLDialect).

AFAKT, Types.BLOB / 'oid' w postgresql powinny być odwzorowane na jakiś niestandardowy typ, który wykorzystuje dostęp JDBC w stylu OID (tj. Obiekt PostgresqlBlobType i NOT MaterializedBlobType). Nigdy tak naprawdę nie korzystałem z Blobów z postgresql, ale wiem, że bytea po prostu działa tak, jak się spodziewałem.

Obecnie patrzę na wyjątek BatchUpdateException - możliwe, że sterownik nie obsługuje przetwarzania wsadowego.


Świetny cytat z 2004 roku: „Podsumowując moje wędrówki, powiedziałbym, że powinniśmy poczekać, aż sterownik JDBC poprawnie wykona LOB przed zmianą Hibernate”.

Bibliografia:

Justin
źródło
Wydaje się, że zostało to naprawione w 3.6, nie jestem pewien co do 3.5.6; Klasa MaterializedBlobType została całkowicie przepisana z 3.5.5> 3.6. Typ OID teraz działa, ponieważ zmienili implementację.
Justin
Miły! Zastanawiam się, jaki problem z Jira polega na śledzeniu tego przepisania, jeśli w ogóle (może przepisanie jest konsekwencją głębszej zmiany). Byłoby miło, jeśli to możliwe, zapisać zmiany w 3.5. Złe wieści, jeśli to niemożliwe.
Pascal Thivent
Właściwie mój test dał mi fałszywie pozytywny wynik za pierwszym razem (wiedziałem, że powinienem poczekać!) - nadal nie jest naprawiony, błąd właśnie został przeniesiony do BlobTypeDescriptor.
Justin
Dzięki. @Type (type = "org.hibernate.type.BinaryType") zadziałało dla mnie w przypadku tabeli przechowującej pliki PDF. Przeprowadziłem migrację bazy danych z Oracle do Postgres przy użyciu Oracle-To-PostgreSQL z Intelligent Converters i automatycznie przekonwertowałem ją i wstawiłem z BLOB do BYTEA, ale BlobType nie działał dla mnie.
jmoran

Odpowiedzi:

68

Jaki jest przenośny sposób dodawania adnotacji do właściwości byte []?

To zależy od tego, czego chcesz. JPA może utrwalać bez adnotacji byte[]. Ze specyfikacji JPA 2.0:

11.1.6 Podstawowe adnotacje

BasicAdnotacji to najprostszy typ mapowania do kolumny bazy danych. BasicAdnotacji mogą być stosowane do trwałego własności lub wystąpienia zmiennej jednego z następujących rodzajów: JAVA prymitywny, rodzaje owinięciom typów pierwotnych, java.lang.String, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, byte[],Byte[] , char[], Character[], teksty stałe i innego rodzaju, które realizuje Serializable. Jak opisano w sekcji 2.8, użycie Basicadnotacji jest opcjonalne dla trwałych pól i właściwości tego typu. Jeśli adnotacja podstawowa nie zostanie określona dla takiego pola lub właściwości, zostaną zastosowane wartości domyślne adnotacji podstawowej.

A Hibernate mapuje go „domyślnie” na SQL VARBINARY(lub SQL w LONGVARBINARYzależności od Columnrozmiaru?), Który PostgreSQL obsługuje z rozszerzeniem bytea.

Ale jeśli chcesz, byte[]aby był przechowywany w dużym obiekcie , powinieneś użyć pliku @Lob. Ze specyfikacji:

11.1.24 Adnotacja Lob

A LobOkreśla adnotacji, że utrzymująca się nieruchomość lub pole powinno być utrwalone w postaci dużego obiektu do dużego typu obiektu bazy danych obsługiwane. Aplikacje przenośne powinny używać Lobadnotacji podczas mapowania na Lobtyp bazy danych . LobAdnotacja może być stosowany w połączeniu z adnotacją podstawowe lub z ElementCollectionadnotacją, kiedy wartość kolekcji jest podstawowym elementem typu. A Lobmoże być typem binarnym lub znakowym. LobTyp jest wywnioskować z typem pola przetrwałym lub mienia oraz, z wyjątkiem ciągów znaków i typów, domyślnie Blob.

Hibernate zamapuje go na SQL BLOBobsługiwany przez PostgreSQL z rozszerzeniem oid .

Czy zostało to naprawione w jakiejś najnowszej wersji hibernacji?

Cóż, problem polega na tym, że nie wiem dokładnie, na czym polega problem. Ale mogę przynajmniej powiedzieć, że nic się nie zmieniło od 3.5.0-Beta-2 (czyli tam, gdzie wprowadzono zmianę) w gałęzi 3.5.x.

Ale moje rozumienie problemów takich jak HHH-4876 , HHH-4617 oraz PostgreSQL i BLOBs (wspomniane w javadoc w PostgreSQLDialect) jest takie, że powinieneś ustawić następującą właściwość

hibernate.jdbc.use_streams_for_binary=false

jeśli chcesz używać oidtj. byte[]z @Lob(co rozumiem, ponieważ VARBINARYnie jest to, czego chcesz w przypadku Oracle). Próbowałeś tego?

Alternatywnie, HHH-4876 sugeruje użycie przestarzałego, PrimitiveByteArrayBlobTypeaby uzyskać stare zachowanie (przed Hibernate 3.5).

Bibliografia

  • Specyfikacja JPA 2.0
    • Sekcja 2.8 „Mapowanie wartości domyślnych dla pól lub właściwości niezwiązanych z relacjami”
    • Sekcja 11.1.6 „Podstawowe adnotacje”
    • Sekcja 11.1.24 „Adnotacja Lob”

Zasoby

Pascal Thivent
źródło
OMG, zdaję sobie sprawę, że to pytanie bardzo się zmieniło, odkąd zacząłem odpowiadać. Przeczytam wszystkie zmiany później i zaktualizuję moje odpowiedzi po przetrawieniu zmian, jeśli to konieczne.
Pascal Thivent
Dobrze jest zobaczyć specyfikację, więc hibernacja jest całkowicie poprawna przy mapowaniu (@Lob + byte []) do obsługiwanego typu dużego obiektu. W Postgresql są 2 (bajt lub oid). Jednak podczas gdy hibernacja 3.5 mapuje na oid (domyślnie), czyta za pomocą JDBC getBytes (), który sterownik PGSQL zwraca 6-bajtowy oid zamiast danych. Zwróć również uwagę, że autor bloga odpowiedział najbardziej (na swoim blogu) od czasu zadania pytania.
Justin
@Justin Jednakże, podczas gdy hibernacja 3.5 mapuje na oid (domyślnie), czyta za pomocą JDBC getBytes (), który sterownik PGSQL zwraca 6-bajtowy oid zamiast danych - czy ma to miejsce podczas używania hibernate.jdbc.use_streams_for_binary=falserównież? (zamierzam teraz sprawdzić, co powiedział Steve).
Pascal Thivent
Spróbuję określić to w pliku właściwości, jednak PostgreSQLDialect ma useInputStreamToInsertBlob () zwraca false, więc zakładam, że tak - ponieważ nie ustawiam jawnie tej właściwości.
Justin
Po ustawieniu tej właściwości (na true lub false) pojawia się wyjątek w czasie wykonywania: BŁĄD: kolumna „podpis” jest typu bajtowego, ale wyrażenie jest typu oid. Powinienem wspomnieć, że używam hibernacji 3.5.5.Final + PG 8.2 kierowców.
Justin
10

Oto, co mówi Oreilly Enterprise JavaBeans 3.0

JDBC ma specjalne typy dla tych bardzo dużych obiektów. Typ java.sql.Blob reprezentuje dane binarne , a java.sql.Clob reprezentuje dane znakowe.

Oto kod źródłowy PostgreSQLDialect

public PostgreSQLDialect() {
    super();
    ...
    registerColumnType(Types.VARBINARY, "bytea");
    /**
      * Notice it maps java.sql.Types.BLOB as oid
      */
    registerColumnType(Types.BLOB, "oid");
}

Więc co możesz zrobić

Zastąp PostgreSQLDialect w następujący sposób

public class CustomPostgreSQLDialect extends PostgreSQLDialect {

    public CustomPostgreSQLDialect() {
        super();

        registerColumnType(Types.BLOB, "bytea");
    }
}

Teraz po prostu zdefiniuj swój własny dialekt

<property name="hibernate.dialect" value="br.com.ar.dialect.CustomPostgreSQLDialect"/>

I użyj przenośnej adnotacji JPA @Lob

@Lob
public byte[] getValueBuffer() {

AKTUALIZACJA

Tutaj został wydobyty tutaj

Mam aplikację działającą w trybie hibernacji 3.3.2 i aplikacje działają dobrze , a wszystkie pola blobów używają oid (bajt [] w java)

...

Migracja do hibernacji 3.5 wszystkie pola blobów już nie działają , a dziennik serwera pokazuje: BŁĄD org.hibernate.util.JDBCExceptionReporter - BŁĄD: kolumna jest typu oid, ale wyrażenie jest typu bajt

co można wyjaśnić tutaj

To generalnie nie błąd w PG JDBC , ale zmiana domyślnej implementacji Hibernate w wersji 3.5 . W mojej sytuacji ustawienie zgodnej właściwości na połączenie nie pomogło .

...

Dużo więcej to co widziałem w 3.5 - beta 2 i nie wiem czy zostało to naprawione to Hibernacja - bez adnotacji @Type - automatycznie utworzy kolumnę typu oid, ale spróbuję odczytać to jako bajt

Interesujące jest to, że kiedy mapuje Types.BOLB jako bajt (patrz CustomPostgreSQLDialect), otrzymuje

Nie można wykonać aktualizacji partii JDBC

podczas wstawiania lub aktualizacji

Arthur Ronald
źródło
To rozwiązanie wygląda wspaniale, próbuję go teraz.
Justin
To generuje poprawny DDL, ale kończy się niepowodzeniem w czasie wykonywania: Otrzymuję wyjątek java.sql.BatchUpdateException podczas próby obiektu z właściwością blob.
Justin
@Justin Wypróbuj podobny scenariusz, używając Oracle zamiast PostgreSQL i zobacz, co otrzymasz. BatchUpdateException ma do czynienia z błędami, które występują podczas operacji aktualizacji wsadowej.
Arthur Ronald
Właściwie to, czego naprawdę chcę, to nie mapowanie BLOBa na "bajt", ale zamiast tego zamapowanie kombinacji adnotacji (bajt [] + @Lob) na Types.VARBINARY!
Justin
7

Używam Hibernate 4.2.7.SP1 z Postgres 9.3 i działa dla mnie:

@Entity
public class ConfigAttribute {
  @Lob
  public byte[] getValueBuffer() {
    return m_valueBuffer;
  }
}

ponieważ Oracle nie ma z tym problemu, a dla Postgres używam niestandardowego dialektu:

public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {

    @Override
    public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
      return BinaryTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
}

Zaletą tego rozwiązania jest to, że mogę utrzymać słoiki w stanie hibernacji nietknięte.

Więcej informacji o problemach ze zgodnością Postgres / Oracle z Hibernate można znaleźć w moim poście na blogu .

Peter Butkovic
źródło
2
Pracowałem dla mnie przy użyciu Hibernate 4.3.6 i Postgresql 9.3 z rozszerzeniem Postgresql9Dialect. Dziękuję Ci!
Andrés Oviedo
Działa z Hibernate 5.3.7.Final i Postgres95Dialect. Thx
Bernhard Kern
6

Wreszcie udało mi się to. Rozwija się na rozwiązaniu A.Garcia, jednak ponieważ problem leży w hibernacji typu MaterializedBlob, samo mapowanie Blob> bajt nie jest wystarczające, potrzebujemy zamiennika dla MaterializedBlobType, który działa z hibernacją zepsutą obsługą blobów. Ta implementacja działa tylko z byteą, ale może facet z JIRA, który chciał OID, mógłby wnieść implementację OID.

Niestety zastępowanie tych typów w czasie wykonywania jest uciążliwe, ponieważ powinny one być częścią Dialektu. Gdyby tylko to rozszerzenie JIRA trafiło do 3.6, byłoby to możliwe.

public class PostgresqlMateralizedBlobType extends AbstractSingleColumnStandardBasicType<byte[]> {
 public static final PostgresqlMateralizedBlobType INSTANCE = new PostgresqlMateralizedBlobType();

 public PostgresqlMateralizedBlobType() {
  super( PostgresqlBlobTypeDescriptor.INSTANCE, PrimitiveByteArrayTypeDescriptor.INSTANCE );
 }

  public String getName() {
   return "materialized_blob";
  }
}

Większość z nich może być prawdopodobnie statyczna (czy getBinder () naprawdę potrzebuje nowej instancji?), Ale tak naprawdę nie rozumiem wewnętrznej hibernacji, więc jest to głównie kopiowanie + wklejanie + modyfikowanie.

public class PostgresqlBlobTypeDescriptor extends BlobTypeDescriptor implements SqlTypeDescriptor {
  public static final BlobTypeDescriptor INSTANCE = new PostgresqlBlobTypeDescriptor();

  public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
   return new PostgresqlBlobBinder<X>(javaTypeDescriptor, this);
  }
  public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
   return new BasicExtractor<X>( javaTypeDescriptor, this ) {
    protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException { 
      return (X)rs.getBytes(name);
    }
   };
  }
}

public class PostgresqlBlobBinder<J> implements ValueBinder<J> {
 private final JavaTypeDescriptor<J> javaDescriptor;
 private final SqlTypeDescriptor sqlDescriptor;

 public PostgresqlBlobBinder(JavaTypeDescriptor<J> javaDescriptor, SqlTypeDescriptor sqlDescriptor) { 
  this.javaDescriptor = javaDescriptor; this.sqlDescriptor = sqlDescriptor;
 }  
 ...
 public final void bind(PreparedStatement st, J value, int index, WrapperOptions options) 
 throws SQLException {
  st.setBytes(index, (byte[])value);
 }
}
Justin
źródło
+1 za twoje badania. Gratulacje. Porada: wolisz edytować własne pytanie / odpowiedź do 8 razy. W przeciwnym razie twoje pytanie / odpowiedź stanie się wiki społeczności i nie zdobędziesz reputacji, a głos W GÓRĘ nie będzie już obliczany
Arthur Ronald
Żyj i ucz się. Przypuszczam, że miałem tak wiele zmian, że ciągle zapominałem o zrobieniu jednej rzeczy w moim środowisku testowym.
Justin
Tak samo tutaj, +1 do badań i do sporządzania roztworu do danej sytuacji.
Pascal Thivent,
jakaś szansa na rozwiązanie w wersji 4.2.x Hibernate? Wewnętrzne elementy hibernacji nieco się zmieniły (skomentowałem kwestię pod adresem: hibernate.atlassian.net/browse/HHH-5584 ).
Peter Butkovic
2

naprawiłem mój problem, dodając adnotację @Lob, która utworzy bajt [] w Oracle jako obiekt blob, ale ta adnotacja utworzy pole jako oid, które nie działa poprawnie. Aby bajt [] został utworzony jako bajt, zrobiłem klient Dialect dla postgres jak poniżej

Public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {
    public PostgreSQLDialectCustom() {
        System.out.println("Init PostgreSQLDialectCustom");
        registerColumnType( Types.BLOB, "bytea" );

      }

    @Override
    public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
      return BinaryTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
 }

Należy również nadpisać parametr dla dialektu

spring.jpa.properties.hibernate.dialect = com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom

więcej podpowiedzi można ją znaleźć: https://dzone.com/articles/postgres-and-oracle

El Ghandor Yasser
źródło
0

Udało mi się to dzięki zastąpieniu adnotacji plikiem XML dla Postgres. Adnotacje są zachowywane dla Oracle. Moim zdaniem w tym przypadku najlepiej byłoby zastąpić mapowanie tego problemu - część z mapowaniem XML. Możemy przesłonić pojedyncze / wiele jednostek za pomocą mapowania XML. Więc użylibyśmy adnotacji dla naszej głównie obsługiwanej bazy danych i pliku xml dla każdej innej bazy danych.

Uwaga: musimy tylko zastąpić jedną klasę, więc nie jest to wielka sprawa. Przeczytaj więcej z mojego przykładu Przykład zastąpienia adnotacji za pomocą XML

Vinh Vo
źródło
0

Na Postgres @Lob łamie byte [], gdy próbuje zapisać go jako oid, a dla String również występuje ten sam problem. Poniższy kod psuje się na postgresach, co działa dobrze na oracle.

@Lob
private String stringField;

i

@Lob
private byte[]   someByteStream;

Aby naprawić powyższy postgres, poniżej napisałem niestandardowy hibernate.dialect

public class PostgreSQLDialectCustom extends PostgreSQL82Dialect{

public PostgreSQLDialectCustom()
{
    super();
    registerColumnType(Types.BLOB, "bytea");
}

 @Override
 public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
      return LongVarcharTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
}

Teraz skonfiguruj niestandardowy dialekt w trybie hibernacji

hibernate.dialect=X.Y.Z.PostgreSQLDialectCustom   

XYZ to nazwa pakietu.

Teraz działa dobrze. UWAGA - Moja wersja Hibernate - 5.2.8. Ostateczna wersja Postgres - 9.6.3

Gajendra Kumar
źródło
0

Dzięki Justin, Pascal za poprowadzenie mnie we właściwym kierunku. Miałem również ten sam problem z Hibernate 3.5.3. Wasze badania i wskazówki dotyczące odpowiednich zajęć pomogły mi zidentyfikować problem i naprawić.

Z korzyścią dla tych, którzy wciąż tkwią w Hibernate 3.5 i używają kombinacji oid + byte [] + @LoB, oto co zrobiłem, aby rozwiązać problem.

  1. Utworzyłem niestandardowy typ BlobType rozszerzający MaterializedBlobType i nadpisując metody set i get z dostępem w stylu oid.

    public class CustomBlobType extends MaterializedBlobType {
    
    private static final String POSTGRESQL_DIALECT = PostgreSQLDialect.class.getName();
    
    /**
     * Currently set dialect.
     */
    private String dialect = hibernateConfiguration.getProperty(Environment.DIALECT);
    
    /*
     * (non-Javadoc)
     * @see org.hibernate.type.AbstractBynaryType#set(java.sql.PreparedStatement, java.lang.Object, int)
     */
    @Override
    public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        byte[] internalValue = toInternalFormat(value);
    
        if (POSTGRESQL_DIALECT.equals(dialect)) {
            try {
    
    //I had access to sessionFactory through a custom sessionFactory wrapper.
    st.setBlob(index, Hibernate.createBlob(internalValue, sessionFactory.getCurrentSession()));
                } catch (SystemException e) {
                    throw new HibernateException(e);
                }
            } else {
                st.setBytes(index, internalValue);
            }
        }
    
    /*
     * (non-Javadoc)
     * @see org.hibernate.type.AbstractBynaryType#get(java.sql.ResultSet, java.lang.String)
     */
    @Override
    public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
        Blob blob = rs.getBlob(name);
        if (rs.wasNull()) {
            return null;
        }
        int length = (int) blob.length();
        return toExternalFormat(blob.getBytes(1, length));
      }
    }
    1. Zarejestruj CustomBlobType w Hibernate. Oto, co zrobiłem, aby to osiągnąć.

      hibernateConfiguration= new AnnotationConfiguration();
      Mappings mappings = hibernateConfiguration.createMappings();
      mappings.addTypeDef("materialized_blob", "x.y.z.BlobType", null);
Nibin Jacob Panicker
źródło