Ich habe Probleme beim Schreiben und Lesen Sonderzeichen wie das Euro-Zeichen (€) in LOB String-Eigenschaften in PostgreSQL 8.4 mit Hibernate 3.6.10.Kann nicht Euro-Zeichen in LOB String Eigenschaft mit Hibernate/PostgreSQL speichern
Ich weiß, dass PostgreSQL zwei verschiedene Möglichkeiten bietet, große Zeichenobjekte in einer Spalte einer Tabelle zu speichern. Sie können entweder direkt in dieser Tabellenspalte oder indirekt in einer separaten Tabelle gespeichert werden (sie heißt eigentlich pg_largeobject). Im letzteren Fall enthält die Spalte eine Referenz (OID) für die Zeile in pg_largeobject.
Das Standardverhalten in Hibernate 3.6.10 ist der indirekte OID-Ansatz. Es ist jedoch möglich, der Eigenschaft Lob eine zusätzliche Anmerkung @ org.hibernate.annotations.Type (type = "org.hibernate.type.TextType") hinzuzufügen, um das Verhalten des direkten Speichers zu erhalten.
Beide Ansätze funktionieren gut, außer für den Moment, dass ich mit Sonderzeichen wie dem Eurozeichen (€) arbeiten möchte. In diesem Fall funktioniert der direkte Speichermechanismus weiter, aber der indirekte Speichermechanismus bricht.
Ich möchte das anhand eines Beispiels demonstrieren. Ich habe eine Testeinheit mit 2 @Lob-Eigenschaften erstellt. Man folgt den direkten Speicherprinzip, das andere die indirekte Lagerung:
@Basic
@Lob
@Column(name = "CLOB_VALUE_INDIRECT_STORAGE", length = 2147483647)
public String getClobValueIndirectStorage()
und
@Basic
@Lob
@org.hibernate.annotations.Type(type="org.hibernate.type.TextType")
@Column(name = "CLOB_VALUE_DIRECT_STORAGE", length = 2147483647)
public String getClobValueDirectStorage()
Wenn ich ein Unternehmen zu erstellen, füllen beide Eigenschaften mit dem Zeichen Euro und es dann bestehen bleiben auf der Datenbank Ich sehe die folgenden, wenn ich eine SELECT sehe ich
id | clob_value_direct_storage | clob_value_indirect_storage
----+---------------------------+----------------------------
6 | € | 910579
Wenn ich dann die Tabelle pg_largeobject Abfrage ich sehe:
loid | pageno | data
--------+--------+------
910579 | 0 | \254
Die 'data'-Spalte von pg_largeobject ist vom Typ bytea, was bedeutet, dass die Information als rohe Bytes gespeichert wird. Der Ausdruck '\ 254' steht für ein einzelnes Byte und in UTF-8 für das Zeichen '¬'. Dies ist genau der Wert, den ich zurückbekomme, wenn ich die Entity von der Datenbank zurücklade.
Die Euro-Zeichen in UTF-8 bestehen aus 3 Bytes, so würde ich die Spalte ‚Daten‘ zu erwarten habe 3 Bytes zu haben und nicht 1.
Dies ist nur für die Euro-Zeichen nicht auftritt, sondern für viele Sonderzeichen. Ist das ein Problem in Hibernate? Oder der JDBC-Treiber? Gibt es eine Möglichkeit, dieses Verhalten zu ändern?
Vielen Dank im Voraus,
Mit freundlichen Grüßen
Franck de Bruijn
Warum sind Sie Große Objekte in erster Linie mit? Verwenden Sie einfach den Datentyp 'text' für diese Spalte. Sie müssen sich nicht mit "bytea" oder großen Objekten herumärgern, wenn Sie nur Text speichern möchten. –
Es könnte viele Gründe geben, dies zu tun. Ich weiß es nicht. Ich biete einen Rahmen für andere Benutzer an und möchte beide Alternativen unterstützen. In älteren Versionen des JDBC-Treibers (oder Hibernate, ich bin mir nicht sicher) war das Standardverhalten "direkter Speicher". Später wurde dies in "indirekte Speicherung" geändert. Wahrscheinlich aus einem guten Grund. –
Ich dachte ein wenig darüber nach und ich stimme mehr und mehr mit a_horse_with_no_name überein. Zunächst einmal verhindert der indirekte Speichermechanismus, dass Sie diese Spalte in einer HQL-Abfrage verwenden, was ein großer Nachteil ist. Der indirekte Speichermechanismus erleichtert die Streaming-Option, sodass Sie den Inhalt direkt von der Datenbank zum Client streamen können (spart Arbeitsspeicher). Sicher ist dies ein gültiges Argument für BLOBs, aber für CLOBs? In den meisten Szenarien wird die Größe der tatsächlichen CLOBs nicht so groß sein, definitiv nicht im Bereich von 1M oder höher. Dies kann im Speicher gehandhabt werden. –