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:
- 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/
Antworten:
Es kommt darauf an, was Sie wollen. JPA kann eine nicht kommentierte beibehalten
byte[]
. Aus der JPA 2.0-Spezifikation:Und Hibernate ordnet es "standardmäßig" einem SQL
VARBINARY
(oder einem SQL,LONGVARBINARY
abhängig von derColumn
Größe?) Zu, das PostgreSQL mit einem verarbeitetbytea
.Wenn Sie jedoch möchten
byte[]
, dass das Objekt in einem großen Objekt gespeichert wird, sollten Sie a verwenden@Lob
. Aus der Spezifikation:Und Hibernate ordnet es einem SQL zu
BLOB
, das PostgreSQL mit einem verarbeitetoid
.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 sollenwenn Sie
oid
dhbyte[]
mit verwenden möchten@Lob
(was nach meinem Verständnis daVARBINARY
nicht das ist, was Sie mit Oracle wollen). Hast du das versucht?Als Alternative schlägt HHH-4876 vor, das veraltete
PrimitiveByteArrayBlobType
Verhalten zu verwenden, um das alte Verhalten zu erhalten (vor dem Ruhezustand 3.5).Verweise
Ressourcen
quelle
hibernate.jdbc.use_streams_for_binary=false
? (werde überprüfen, was Steve jetzt gesagt hat).Hier ist, was O'reilly Enterprise JavaBeans, 3.0 sagt
Hier geht es zum PostgreSQLDialect-Quellcode
Also, was können Sie tun?
Überschreiben Sie PostgreSQLDialect wie folgt
Definieren Sie jetzt einfach Ihren benutzerdefinierten Dialekt
Verwenden Sie auch Ihre tragbare JPA @ Lob-Annotation
AKTUALISIEREN
Hier wurde extrahiert hier
...
was hier erklärt werden kann
...
Interessant ist, dass er bekommt, wenn er Types.BOLB als bytea abbildet (siehe CustomPostgreSQLDialect)
beim Einfügen oder Aktualisieren
quelle
Ich verwende den Ruhezustand 4.2.7.SP1 mit Postgres 9.3 und folgende Arbeiten für mich:
Da Oracle damit keine Probleme hat und ich für Postgres einen benutzerdefinierten Dialekt verwende:
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 .
quelle
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.
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.
quelle
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
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
quelle
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
quelle
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.
und
Um oben auf Postgres zu beheben, haben unten benutzerdefinierte hibernate.dialect geschrieben
Konfigurieren Sie nun den benutzerdefinierten Dialekt im Ruhezustand
XYZ ist der Paketname.
Jetzt funktioniert es gut. HINWEIS - Meine Version im Ruhezustand - 5.2.8.Final Postgres Version - 9.6.3
quelle
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.
Ich habe einen benutzerdefinierten BlobType erstellt, der MaterializedBlobType erweitert und die Set- und Get-Methoden mit dem Zugriff auf den OID-Stil überschreibt.
Registrieren Sie den CustomBlobType im Ruhezustand. Folgendes habe ich getan, um das zu erreichen.
quelle