2013-01-24 10 views
10

Wir haben eine PPV kommentierte Art verwenden, die so (groovy Code) sieht:Wie migriere ich PostgreSQL-Zeichenfolgen in einen Texttyp?

@Entity 
@EqualsAndHashCode 
class TextNote extends Serializable { 
    @Id Long id 
    String text 
} 

Als es zuerst die SQL erste machte ich war geschrieben wurde sehr neu in JPA und schrieb, dann sind die kommentierten Klassen die passen SQL. Lesen auf PostgreSQL schien es wie folgt aus der Tisch war ich wollte:

CREATE TABLE textnote (
    id bigint NOT NULL, 
    text text 
); 

Das funktionierte, und wir hatten Tische, die wie folgt aussah:

id |   text 
-----+------------------------ 
837 | really long text here 

Was will ich jetzt zu tun ist, korrekt die JPA Entity zu sehen wie folgt aus:

@Entity 
@EqualsAndHashCode 
class TextNote extends Serializable { 
    @Id Long id 
    @Lob String text 
} 

Durch das Hinzufügen der @Lob Anmerkung der JPA-Provider (in meinem Fall, hibernate) könnte die DDL richtig für mich, falls erzeugen Wir wollen Datenbanken austauschen. Es dokumentiert auch genau, was ich will, dass das Textfeld ist. Nun, wenn eine Notiz erstellt wird, ich sehe etwas wie folgt aus:

id |   text 
-----+------------------------ 
837 | 33427 

, die für neue Noten in Ordnung ist, als wenn ich es in Code String getText lesen() es gibt den wirklich langen Text. Ehrlich gesagt weiß ich nicht, wie PostgreSQL den text Typ implementiert, noch sollte ich in der Theorie brauchen. In unserer Produktionsdatenbank sind jedoch bereits viele Notizen mit altem Code ohne die @Lob Annotation gespeichert. Das Ausführen des neuen Code auf einer vorhandenen Datenbank erzeugt Fragen wie diese:

org.springframework.dao.DataIntegrityViolationException: Bad value for type long : not a number this time; SQL [n/a]; nested exception is org.hibernate.exception.DataException: Bad value for type long : not a number this time 

Für bestehende Notizen, gibt es eine Möglichkeit in SQL die alten Noten zu migrieren @Lob und text Typ korrekt zu benutzen? Danke im Voraus.

Antwort

12

Basierend auf der Postgres large object docs sieht es so aus, als müssten Sie jeden Textabschnitt in eine Datei schreiben und einzeln importieren. Was Sie nicht in SQL machen sollten.

Ich weiß nichts über JPA, aber was hat @Lob mit DDL oder Switching-Datenbanken zu tun? Sie haben den Typ der Spalte vollständig geändert. Was stimmt nicht mit dem Typ text von Postgres?

Das eigentliche Problem text Spalt, aber Hibernate treats it als native Postgres „großes Objekt“, die Daten an anderer Stelle speichert eine Postgres war, dass @Lob erstellt:


die Schleife hier Closing so ist dies in den Kommentaren nicht verloren und hinterlässt nur eine oid in der Tabelle (die dann als Text gespeichert wurde, gemäß dem Spaltentyp). Dies ist normalerweise nicht das, was Sie für Text wollen.

Die Lösung von OP bestand darin, auf @Type(type="org.hibernate.type.StringClobType") zu klopfen, um Hibernate zum Speichern von normalem Text zu zwingen.

Postgres speichert Text normalerweise nicht als fünfstellige Ganzzahl. :)

+0

Ohne diese Anmerkung würden die JPA-Provider eine Tabelle mit Spaltentyp varchar erzeugen, das nicht das, was ich will. '@ Lob' erzeugt den PostgreSQL' text' Typ, was genau das ist, was ich will. Wenn ich Datenbanken wechseln wollte, würde ich den JPA-Provider verwenden, um die DDL für mich zu generieren. '@ Lob' ist notwendig, um dies zu tun. Sinn ergeben? – Joe

+0

Sind Sie sicher, '@ Lob' erzeugt' text'? Sowohl die Dokumentation als auch die von Ihnen gepostete Ausgabe lassen mich denken, dass sie "oid" generieren würde - so speichert Postgres große Objekte. Wenn es wirklich "Text" wäre, würden Sie nur _text_ sehen, keine Mystery-Nummer. – Eevee

+0

Ich bin positiv, hier ist die Tabelle, die es mit der '@ Lob' Annotation ausgibt: [gist] (https://gist.github.com/4630173) – Joe

7

Ich verwende JPA, um meine Entitäten zu kommentieren und Hibernate, um sie zu erhalten. Aber ich möchte meinen Entitäten keine Hibernate-spezifischen Anmerkungen hinzufügen. Daher habe ich ein Daten-Jar mit den Entitäten + Annotationen. Dann gebe ich in meiner Implementierung die persistence.xml an und füge eine 'CustomTypes.hbm.xml' hinzu.Dies wird automatisch gescannt oder über das Mapping-Datei-Tag in der Datei persistence.xml hinzugefügt.

Diese Zuordnung enthält die Typen, die ich aus der Basistypregistry überschreiben möchte. In diesem Fall wird der Typ materialized_clob verwendet. Was ich nicht will, denn wenn ich meine Datenbank mit einem Abfragetool durchblättere, möchte ich den eigentlichen Inhalt direkt sehen können. So füge ich:

<typedef name="materialized_clob" class="org.hibernate.type.TextType" /> 

für all CLOBs die Verwendung des angegebenen Typs zu erzwingen, ohne die Notwendigkeit, spezifische Anmerkungen in meinem Datenpaket hinzuzufügen.

Sie können die Zuordnungen überprüfen, indem Sie org.hibernate.type.BasicTypeRegistry auf DEBUG-Ebene protokollieren.

Ich brauchte einige Zeit, um das herauszufinden und ich hoffe, dass dies jedem helfen wird, der die gleichen Probleme hat. Da dies wahrscheinlich auch Ihr Problem lösen wird, dachte ich, dass es sich lohnt, es hier zu veröffentlichen.

0

Wenn Sie eine Feder verwenden, können Sie LocalSessionFactoryBean Nachkommen erstellen, um Hibernate-Typ-Overrides zu injizieren. Siehe Beispiel:

public class CustomSessionFactoryBean extends LocalSessionFactoryBean { 

    @Override 
    protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { 
     // To store @Lob annotated Strings in TEXT fields. 
     // By default for Postgres generated TEXT column, but stored OID of Postgres LOB object 
     sfb.registerTypeOverride(new TextType() { 
      @Override 
      public String getName() { 
       return StandardBasicTypes.MATERIALIZED_CLOB.getName(); 
      } 
     }); 
     sfb.registerTypeOverride(new NTextType() { 
      @Override 
      public String getName() { 
       return StandardBasicTypes.MATERIALIZED_NCLOB.getName(); 
      } 
     }); 

     super.buildSessionFactory(sfb); 
    } 
} 

Sie brauchen nicht zu Hibernate Annotations spezifische @Type zu verwenden, mit Anmerkungen versehen nur String-Eigenschaft mit @Lob und verwenden CustomSessionFactoryBean

1

Ich bin sicher, dass sein zu spät, aber für jemand mit dem gleichen Problem in Zukunft .

Ich konfrontiert auch ein ähnliches Problem, wo ich alte Daten in den Spalten des Textes direkt in den Spalten nicht als OIDs hatte. Und wenn ich versuche, diese Daten zu verwenden, um mit aktualisierten Anwendung zu ich war immer

Bad value for type long 

das ich this script erstellt zu beheben. Vielleicht kann es jemandem in Zukunft helfen.

ich eine große Hilfe von diesem Posten bekam here

Verwandte Themen