richtige Annotation im Ruhezustand für Byte []

120

Ich habe eine Anwendung, die Anmerkungen zu Ruhezustand 3.1 und JPA verwendet. Es enthält einige Objekte mit Byte [] -Attributen (1k - 200k groß). Es verwendet die Annotation JPA @Lob, und Hibernate 3.1 kann diese in allen wichtigen Datenbanken problemlos lesen - es scheint die Besonderheiten des JDBC-Blob-Anbieters zu verbergen (wie es sein sollte).

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

Wir mussten auf 3.5 aktualisieren, als wir feststellten, dass der Ruhezustand 3.5 diese Annotationskombination in postgresql (ohne Problemumgehung) unterbricht ( und nicht behebt ). Ich habe bisher keine eindeutige Lösung gefunden, aber ich habe festgestellt, dass beim Entfernen von @Lob der Postgresql-Typ bytea verwendet wird (was funktioniert, jedoch nur bei 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.

Ich suche nach einer Möglichkeit, eine einzelne kommentierte Klasse (mit einer Blob-Eigenschaft) zu haben, die über wichtige Datenbanken hinweg portierbar ist.

  • Wie kann eine byte [] -Eigenschaft portabel kommentiert werden?
  • Ist dies in einer neueren Version des Ruhezustands behoben?

Update: Nachdem ich diesen Blog gelesen habe, habe ich endlich herausgefunden, wie die ursprüngliche Problemumgehung in der JIRA-Ausgabe lautete: Anscheinend sollten Sie @Lob löschen und die Eigenschaft wie folgt kommentieren:

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

Dies funktioniert jedoch nicht für mich - ich erhalte immer noch OIDs anstelle von Bytea; es funktionierte jedoch für den Autor der JIRA-Ausgabe, der anscheinend oid wollte.

Nach der Antwort von A. Garcia habe ich dann diese Combo ausprobiert, die tatsächlich auf postgresql funktioniert, aber nicht auf oracle.

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

Was ich wirklich tun muss, ist zu steuern, welcher @ org.hibernate.annotations.Type die Kombination (@Lob + Byte [] wird zugeordnet) (auf postgresql).


Hier ist das Snippet von 3.5.5.Final von MaterializedBlobType (SQL-Typ Blob). Laut Steves Blog möchte postgresql, dass Sie Streams für bytea (fragen Sie mich nicht warum) und postgresqls benutzerdefinierten Blob-Typ für oids verwenden. Beachten Sie auch, dass die Verwendung von setBytes () unter JDBC auch für bytea gilt (aus früheren Erfahrungen). Dies erklärt also, warum Use-Streams keinen Einfluss darauf haben, dass beide "Bytea" annehmen.

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

Das führt zu:

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

Update Die nächste logische Frage lautet: "Warum nicht einfach die Tabellendefinitionen manuell in bytea ändern" und das (@Lob + byte []) beibehalten? Dies funktioniert , BIS Sie versuchen, ein Null-Byte [] zu speichern. Was der postgreSQL-Treiber für einen Ausdruck vom Typ OID hält und der Spaltentyp bytea ist, liegt daran, dass der Ruhezustand (zu Recht) JDBC.setNull () anstelle von JDBC.setBytes (null) aufruft, was der PG-Treiber erwartet.

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

Das Typsystem im Ruhezustand ist derzeit in Arbeit (gemäß 3.5.5 Verfallskommentar). Tatsächlich ist so viel vom 3.5.5-Code veraltet, dass es schwierig ist zu wissen, worauf zu achten ist, wenn PostgreSQLDialect unterklassifiziert wird.

AFAKT, Types.BLOB / 'oid' auf postgresql sollte einem benutzerdefinierten Typ zugeordnet werden, der JDBC-Zugriff im OID-Stil verwendet (dh PostgresqlBlobType-Objekt und NOT MaterializedBlobType). Ich habe Blobs noch nie erfolgreich mit postgresql verwendet, aber ich weiß, dass bytea einfach so funktioniert, wie ich es erwarten würde.

Ich sehe mir gerade die BatchUpdateException an - es ist möglich, dass der Treiber das Batching nicht unterstützt.


Tolles Zitat aus dem Jahr 2004: "Um meine Streifzüge zusammenzufassen, ich würde sagen, wir sollten warten, bis der JDBC-Treiber die LOBs ordnungsgemäß ausgeführt hat, bevor wir den Ruhezustand ändern."

Verweise:

Justin
quelle
Dies scheint in 3.6 behoben worden zu sein, nicht sicher über 3.5.6; Die MaterializedBlobType-Klasse wurde von 3.5.5> 3.6 komplett neu geschrieben. Der OID-Typ funktioniert jetzt, da die Implementierung geändert wurde.
Justin
Nett! Ich frage mich, welches Jira-Problem diese Neufassung verfolgt, wenn überhaupt (möglicherweise ist die Neufassung eine Folge einer tieferen Änderung). Es wäre schön, wenn Sie die Änderungen in 3.5 nach Möglichkeit zurückportieren würden. Schlechte Nachrichten, wenn es nicht möglich ist.
Pascal Thivent
Tatsächlich gab mir mein Test beim ersten Mal ein falsches Positiv (ich wusste, ich hätte warten sollen!) - es ist immer noch nicht behoben, der Fehler wurde gerade auf BlobTypeDescriptor verschoben.
Justin
Vielen Dank. @Type (type = "org.hibernate.type.BinaryType") arbeitete für mich für eine Tabelle, in der PDF-Dateien gespeichert sind. Ich habe eine Datenbank von Oracle nach Postgres mit Oracle-To-PostgreSQL von Intelligent Converters migriert und sie automatisch konvertiert und von BLOB nach BYTEA eingefügt, aber BlobType hat bei mir nicht funktioniert.
Jmoran

Antworten:

68

Wie kann eine byte [] -Eigenschaft portabel kommentiert werden?

Es kommt darauf an, was Sie wollen. JPA kann eine nicht kommentierte beibehalten byte[]. Aus der JPA 2.0-Spezifikation:

11.1.6 Grundlegende Anmerkung

Die BasicAnmerkung ist die einfachste Art der Zuordnung zu einer Datenbankspalte. Die BasicAnmerkung kann zu einem persistenten Eigenschaft oder Instanzvariable eine der folgenden Arten angewandt werden: Java primitive, Typen, Umhüllungen der primitiven Typen, 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[], Aufzählungen, und jede andere Art , dass Geräte Serializable. Wie in Abschnitt 2.8 beschrieben, ist die Verwendung der BasicAnmerkung für persistente Felder und Eigenschaften dieser Typen optional. Wenn für ein solches Feld oder eine solche Eigenschaft keine Basisanmerkung angegeben ist, gelten die Standardwerte der Basisanmerkung.

Und Hibernate ordnet es "standardmäßig" einem SQL VARBINARY(oder einem SQL, LONGVARBINARYabhängig von der ColumnGröße?) Zu, das PostgreSQL mit einem verarbeitet bytea.

Wenn Sie jedoch möchten byte[], dass das Objekt in einem großen Objekt gespeichert wird, sollten Sie a verwenden @Lob. Aus der Spezifikation:

11.1.24 Lob Annotation

Eine LobAnmerkung gibt an, dass eine persistente Eigenschaft oder ein beständiges Feld als großes Objekt für einen datenbankgestützten großen Objekttyp beibehalten werden soll. Tragbare Anwendungen sollten die LobAnmerkung verwenden, wenn sie einem Datenbanktyp zugeordnet Lobwerden. Die LobAnnotation kann in Verbindung mit der Basisanmerkung oder mit der ElementCollectionAnnotation verwendet werden, wenn der Elementauflistungswert vom Basistyp ist. A Lobkann entweder ein Binär- oder ein Zeichentyp sein. Der LobTyp wird aus dem Typ des persistenten Felds oder der persistenten Eigenschaft abgeleitet und ist mit Ausnahme der Zeichenfolgen- und Zeichentypen standardmäßig Blob.

Und Hibernate ordnet es einem SQL zu BLOB, das PostgreSQL mit einem verarbeitet oid .

Ist dies in einer neueren Version des Ruhezustands behoben?

Das Problem ist, dass ich nicht genau weiß, wo das Problem liegt. Aber ich kann zumindest sagen, dass sich seit 3.5.0-Beta-2 (wo eine Änderung eingeführt wurde) im 3.5.x-Zweig nichts geändert hat.

Mein Verständnis von Problemen wie HHH-4876 , HHH-4617 sowie von PostgreSQL und BLOBs (im Javadoc von erwähnt PostgreSQLDialect) ist jedoch, dass Sie die folgende Eigenschaft festlegen sollen

hibernate.jdbc.use_streams_for_binary=false

wenn Sie oiddh byte[]mit verwenden möchten @Lob(was nach meinem Verständnis da VARBINARYnicht das ist, was Sie mit Oracle wollen). Hast du das versucht?

Als Alternative schlägt HHH-4876 vor, das veraltete PrimitiveByteArrayBlobTypeVerhalten zu verwenden, um das alte Verhalten zu erhalten (vor dem Ruhezustand 3.5).

Verweise

  • JPA 2.0-Spezifikation
    • Abschnitt 2.8 "Zuordnungsstandards für Felder oder Eigenschaften ohne Beziehung"
    • Abschnitt 11.1.6 "Grundlegende Anmerkung"
    • Abschnitt 11.1.24 "Lob Annotation"

Ressourcen

Pascal Thivent
quelle
OMG, mir ist klar, dass sich diese Frage sehr verändert hat, seit ich angefangen habe zu antworten. Liest alle Änderungen später und aktualisiert meine Antworten, nachdem ich die Änderungen bei Bedarf verdaut habe.
Pascal Thivent
Es ist gut, die Spezifikation zu sehen, daher ist der Ruhezustand völlig korrekt, um (@Lob + Byte []) einem von großen Objekten unterstützten Typ zuzuordnen. In Postgresql gibt es 2 (Bytea oder Oid). Während der Ruhezustand 3.5 (standardmäßig) oid zugeordnet ist, wird mit JDBC getBytes () gelesen, welcher PGSQL-Treiber die 6-Byte-oid anstelle der Daten zurückgibt. Beachten Sie auch, dass der Blog-Autor (in seinem Blog) am hilfreichsten geantwortet hat, seit die Frage gestellt wurde.
Justin
@Justin Während der Ruhezustand 3.5 (standardmäßig) oid zugeordnet ist, wird mit JDBC getBytes () gelesen, welcher PGSQL-Treiber die 6-Byte-oid anstelle der Daten zurückgibt. Tritt dies auch bei Verwendung auf hibernate.jdbc.use_streams_for_binary=false? (werde überprüfen, was Steve jetzt gesagt hat).
Pascal Thivent
Ich werde versuchen, es in der Eigenschaftendatei anzugeben, aber PostgreSQLDialect hat useInputStreamToInsertBlob (), das false zurückgibt, also gehe ich davon aus, dass ich es bin - da ich diese Eigenschaft nicht explizit festlege.
Justin
Nachdem ich diese Eigenschaft auf true oder false gesetzt habe, wird eine Laufzeitausnahme angezeigt: FEHLER: Die Spalte "Signatur" ist vom Typ bytea, aber der Ausdruck ist vom Typ oid. Ich sollte erwähnen, dass ich den Ruhezustand 3.5.5.Final + PG verwende 8.2 Fahrer.
Justin
10

Hier ist, was O'reilly Enterprise JavaBeans, 3.0 sagt

JDBC hat spezielle Typen für diese sehr großen Objekte. Der Typ java.sql.Blob repräsentiert Binärdaten und java.sql.Clob repräsentiert Zeichendaten.

Hier geht es zum PostgreSQLDialect-Quellcode

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

Also, was können Sie tun?

Überschreiben Sie PostgreSQLDialect wie folgt

public class CustomPostgreSQLDialect extends PostgreSQLDialect {

    public CustomPostgreSQLDialect() {
        super();

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

Definieren Sie jetzt einfach Ihren benutzerdefinierten Dialekt

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

Verwenden Sie auch Ihre tragbare JPA @ Lob-Annotation

@Lob
public byte[] getValueBuffer() {

AKTUALISIEREN

Hier wurde extrahiert hier

Ich habe eine Anwendung im Ruhezustand 3.3.2 und die Anwendungen funktionieren einwandfrei , wobei alle Blob-Felder oid (byte [] in Java) verwenden.

...

Bei der Migration in den Ruhezustand 3.5 funktionieren alle Blob-Felder nicht mehr . Das Serverprotokoll zeigt: ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: Die Spalte ist vom Typ oid, aber der Ausdruck ist vom Typ bytea

was hier erklärt werden kann

Dies ist im Allgemeinen kein Fehler in PG JDBC , sondern eine Änderung der Standardimplementierung von Hibernate in Version 3.5 . In meiner Situation hat es nicht geholfen, eine kompatible Eigenschaft für die Verbindung festzulegen .

...

Viel mehr als das, was ich in 3.5 - Beta 2 gesehen habe, und ich weiß nicht, ob dies behoben wurde, ist Hibernate - ohne @ Type-Annotation - automatisch eine Spalte vom Typ oid zu erstellen, aber ich werde versuchen, dies als bytea zu lesen

Interessant ist, dass er bekommt, wenn er Types.BOLB als bytea abbildet (siehe CustomPostgreSQLDialect)

Konnte nicht das JDBC batch Update ausführen

beim Einfügen oder Aktualisieren

Arthur Ronald
quelle
Diese Lösung sieht großartig aus, ich versuche es jetzt.
Justin
Dies generiert die richtige DDL, schlägt jedoch zur Laufzeit fehl: Ich erhalte eine java.sql.BatchUpdateException, wenn ich versuche, ein Objekt mit einer Blob-Eigenschaft zu bearbeiten.
Justin
@Justin Versuchen Sie ein ähnliches Szenario, indem Sie Oracle anstelle von PostgreSQL verwenden, und sehen Sie, was Sie erhalten. BatchUpdateException hat mit Fehlern zu tun, die während einer Stapelaktualisierung auftreten.
Arthur Ronald
Eigentlich möchte ich BLOB nicht "bytea" zuordnen, sondern stattdessen die Annotationskombination (byte [] + @Lob) Types.VARBINARY zuordnen!
Justin
7

Ich verwende den Ruhezustand 4.2.7.SP1 mit Postgres 9.3 und folgende Arbeiten für mich:

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

Da Oracle damit keine Probleme hat und ich für Postgres einen benutzerdefinierten Dialekt verwende:

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

Der Vorteil dieser Lösung ist meiner Meinung nach, dass ich die Gläser im Winterschlaf unberührt lassen kann.

Weitere Postgres / Oracle-Kompatibilitätsprobleme mit Hibernate finden Sie in meinem Blogbeitrag .

Peter Butkovic
quelle
2
Arbeitete für mich mit Hibernate 4.3.6 und Postgresql 9.3 mit der Erweiterung von Postgresql9Dialect. Danke dir!
Andrés Oviedo
Funktioniert mit Hibernate 5.3.7.Final und Postgres95Dialect. Thx
Bernhard Kern
6

Ich habe es endlich geschafft. Es erweitert jedoch die Lösung von A. Garcia. Da das Problem jedoch im Ruhezustandstyp MaterializedBlob liegt, reicht es nicht aus, nur Blob> bytea zuzuordnen. Wir benötigen einen Ersatz für MaterializedBlobType, der mit Unterstützung für defekte Blobs im Ruhezustand funktioniert. Diese Implementierung funktioniert nur mit bytea, aber vielleicht könnte der Typ aus dem JIRA-Problem, der OID wollte, eine OID-Implementierung beitragen.

Leider ist das Ersetzen dieser Typen zur Laufzeit ein Problem, da sie Teil des Dialekts sein sollten. Wenn nur diese JIRA-Erweiterung auf 3.6 kommt, wäre dies möglich.

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

Vieles davon könnte wahrscheinlich statisch sein (benötigt getBinder () wirklich eine neue Instanz?), Aber ich verstehe den internen Ruhezustand nicht wirklich, daher ist dies meistens Kopieren + Einfügen + Ändern.

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
quelle
+1 für Ihre Forschung. Herzliche Glückwünsche. Nur ein Rat: Bearbeiten Sie Ihre eigene Frage / Antwort lieber bis zu 8 Mal. Andernfalls wird Ihre Frage / Antwort zum Community-Wiki und Sie gewinnen keinen Ruf und die UP-Abstimmung wird nicht mehr berechnet
Arthur Ronald
Lebe und lerne, ich nehme an, ich hatte so viele Änderungen, dass ich immer wieder vergaß, das eine oder andere mit meiner Testumgebung zu tun.
Justin
Gleich hier, +1 für die Recherche und eine Lösung für Ihre Situation.
Pascal Thivent
Gibt es eine Chance auf eine Lösung mit der Version 4.2.x Hibernate? Interna im Ruhezustand haben sich etwas geändert (ich habe das Problem erneut kommentiert: hibernate.atlassian.net/browse/HHH-5584 ).
Peter Butkovic
2

Ich habe mein Problem behoben, indem ich die Annotation von @Lob hinzugefügt habe, die das Byte [] in Oracle als Blob erstellt. Durch diese Annotation wird jedoch das Feld als OID erstellt, das nicht ordnungsgemäß funktioniert postgres wie unten

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

Außerdem müssen Parameter für den Dialekt überschrieben werden

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

Weitere Hinweise finden Sie unter: https://dzone.com/articles/postgres-and-oracle

El Ghandor Yasser
quelle
0

Ich habe es geschafft, indem ich die Annotation mit der XML-Datei für Postgres überschrieben habe. Anmerkungen werden für Oracle aufbewahrt. Meiner Meinung nach ist es in diesem Fall am besten, die Zuordnung dieser Probleme mit der XML-Zuordnung zu überschreiben. Wir können einzelne / mehrere Entitäten mit XML-Mapping überschreiben. Wir würden also Anmerkungen für unsere hauptsächlich unterstützte Datenbank und eine XML-Datei für die jeweils andere Datenbank verwenden.

Hinweis: Wir müssen nur eine einzelne Klasse überschreiben, es ist also keine große Sache. Lesen Sie mehr aus meinem Beispielbeispiel, um Anmerkungen mit XML zu überschreiben

Vinh Vo
quelle
0

Auf Postgres bricht @Lob für Byte [], da es versucht, es als OID zu speichern, und für String tritt dasselbe Problem auf. Der folgende Code bricht auf Postgres, was auf Orakel gut funktioniert.

@Lob
private String stringField;

und

@Lob
private byte[]   someByteStream;

Um oben auf Postgres zu beheben, haben unten benutzerdefinierte hibernate.dialect geschrieben

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

Konfigurieren Sie nun den benutzerdefinierten Dialekt im Ruhezustand

hibernate.dialect=X.Y.Z.PostgreSQLDialectCustom   

XYZ ist der Paketname.

Jetzt funktioniert es gut. HINWEIS - Meine Version im Ruhezustand - 5.2.8.Final Postgres Version - 9.6.3

Gajendra Kumar
quelle
0

Danke Justin, Pascal, dass du mich in die richtige Richtung geführt hast. Ich hatte auch das gleiche Problem mit Hibernate 3.5.3. Ihre Recherchen und Hinweise auf die richtigen Klassen haben mir geholfen, das Problem zu identifizieren und eine Lösung zu finden.

Für diejenigen, die immer noch mit Hibernate 3.5 nicht weiterkommen und die Kombination oid + byte [] + @LoB verwenden, habe ich Folgendes getan, um das Problem zu beheben.

  1. Ich habe einen benutzerdefinierten BlobType erstellt, der MaterializedBlobType erweitert und die Set- und Get-Methoden mit dem Zugriff auf den OID-Stil überschreibt.

    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. Registrieren Sie den CustomBlobType im Ruhezustand. Folgendes habe ich getan, um das zu erreichen.

      hibernateConfiguration= new AnnotationConfiguration();
      Mappings mappings = hibernateConfiguration.createMappings();
      mappings.addTypeDef("materialized_blob", "x.y.z.BlobType", null);
Nibin Jacob Panicker
quelle