2012-07-01 14 views
22

私は主キーとしてUUIDを使用するPostgreSQLのエンティティを永続化しようとしています。 I平野UUIDとしてそれを永続化しようとしました。以上によりJPAを使用したPostgreSQLでのUUIDの永続化

@Id 
@Column(name = "customer_id") 
private UUID id; 

、私はこのエラーを取得:

ERROR: column "customer_id" is of type uuid but expression is of type bytea 
Hint: You will need to rewrite or cast the expression. 
Position: 137 

私も無駄に[]バイトとしてUUIDを永続化しようとした:

@Transient 
private UUID id; 

@Id 
@Column(name = "customer_id") 
@Access(AccessType.PROPERTY) 
@Lob 
protected byte[] getRowId() { 
    return id.toString().getBytes(); 
} 

protected void setRowId(byte[] rowId) { 
    id = UUID.fromString(new String(rowId)); 
} 

@Lobを削除した場合、私が得るエラーは上記のものと同じです。私はこのような単純な何かを行うことができない非常に悪い感じている

ERROR: column "customer_id" is of type uuid but expression is of type bigint 
Hint: You will need to rewrite or cast the expression. 
Position: 137 

:しかし@Lobでわずかに、エラー変更を適用!

私はPostgreSQL 9.1でHibernate 4.1.3.Finalを使用しています。

私は多かれ少なかれ同じ問題で多くの質問を見ましたが、それらはすべて古いものであり、まったく正直な答えはないようです。

私は醜いハッキングに頼らずに標準的な方法でこれを達成したいと思います。しかし、これが(醜い)ハッキングでしか達成できないなら、それは私がすることです。しかし、UUIDをvarcharとしてデータベースに格納したくないのは、性能が良くないからです。また、可能であれば、私のコードにHibernate依存関係を導入したくないでしょう。

任意の助けいただければ幸いです。

UPDATE 1(2012-07-03 12:15)

まあ、まあ、まあ...それは私がまったく同じコード(プレーンUUID、無変換をテストしたことをちょっと面白いです - JTDSドライバ(v1.2.5)を使用してSQL Server 2008 R2をインストールし、それが魅力的であった(もちろん、persistence.xmlの接続関連情報を変更しなければならなかった)。

さて、PostgreSQL特有の問題なのでしょうか?

+1

[HibernateでサポートされているPostgreSQL UUID?](http://stackoverflow.com/questions/4495233/postgresql-uuid-supported-by -hibernate) –

+0

私の記事で言及したように、同じ問題を抱えているので、多くの質問がありますが、それらはすべて古いものであり、優れた解決策を持っていないようです。あなたが言及した投稿は例外ではありません(私の質問を投稿する前にbtwを見ました)。 – ehsanullahjan

答えて

30

PostgreSQL JDBCドライバは、残念ながらJDBC以外の標準タイプコードを表す方法を選択しています。彼らは単にそれらのすべてをTypes.OTHERにマップします。かいつまんで、あなたは(postgresの固有のUUIDデータ型の列に)UUIDマッピングを処理するための特殊なHibernate型マッピングを有効にする必要があります。

@Id 
@Column(name = "customer_id") 
@org.hibernate.annotations.Type(type="org.hibernate.type.PostgresUUIDType") 
private UUID id; 

以上簡潔に:

@Id 
@Column(name = "customer_id") 
@org.hibernate.annotations.Type(type="pg-uuid") 
private UUID id; 

別の(よりよいです)オプションは、org.hibernate.type.PostgresUUIDTypeを、java.util.UUIDとして公開されているすべての属性のデフォルトのHibernate型マッピングとして登録することです。

@javax.persistence.Converter(autoApply = true) 
public class PostgresUuidConverter implements AttributeConverter<UUID, UUID> { 

    @Override 
    public UUID convertToDatabaseColumn(UUID attribute) { 
     return attribute; 
    } 

    @Override 
    public UUID convertToEntityAttribute(UUID dbData) { 
     return dbData; 
    } 

} 

ちょうどあなたにこのクラスを追加します。それはhttp://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch06.html#types-registry

+1

+1これはうまくいきました:@ org.hibernate.annotations.Type(type = "pg-uuid") – ehsanullahjan

+0

こんにちは、私はこれを試しましたが、私はorg.hibernate.MappingExceptionを持っています:いいえ、JDBCタイプの方言マッピング:1111誰でもできます助けて? – jonfornari

+0

@jonfornari同じ問題がありましたが、Grailsプロジェクトでorg.hibernate.dialect.PostgreSQLDialectを選択するのを忘れました。多分あなたはその設定や他の設定を見失っているでしょうか?私は次のものは必要ありませんでしたが、それはあなたを助けるかもしれません:http://andrew-arch.blogspot.com/2008/02/uuid-and-hibernate-second-update.html –

-4

レコードのUUIDを生成すると、静的になります。したがって、UUIDをオブジェクトとしてデータベースにマッピングしてから、それを検索時にStringに変換する必要はありません。文字列として

利用UUID:

@Id 
@Column(name = "customer_id") 
private String id; 

//getter and setter 

public void setId(UUID id) { 
    this.id = id.toString(); 
} 

も考慮すべきいくつかのものがあります。

  1. ID、UUIDまたはその両方を使用するかどうか。 quick discussion over thisがあります。
  2. 「id」ではなく「uuid」を使用すると、誤解を招きます。
  3. UUIDから ' - '記号を削除すると、4バイトを節約できます。
  4. Springを使用する場合は、@PrePersistセクションでUUIDを生成してください。
+0

あなたの答えをありがとうが、あなたは私の質問を完全には行かなかったようです。データベースに文字列(varchar)としてUUIDを格納することは、パフォーマンスを傷つけることになり、考慮するオプションではないとすでに言及しました。 DBのネイティブタイプ(varcharと比較して)としてUUIDを格納している限り、 ''で再生する必要はありません。コーディング・ホラー・リンクに関しては、私はすでにそれを行ってきました。 – ehsanullahjan

+0

また、私がuuid-string-uuid変換を行った全理由は、最初のエラーを回避することでした。しかし、質問に記載されているように、それは動作しませんでした。 – ehsanullahjan

+0

@ janlalaあなたはまだIDをLongとして作ることができますが、それはパフォーマンスを節約しますか? – JMelnik

13

JPA 2.1は、対応するエンティティのフィールドのタイプとしてPostgreSQLのUUIDのカラム型とjava.util.UUIDを使用するための非常に簡単な方法を提供し、@ドキュメンテーションで覆われています。永続性設定を行い、UUIDフィールドに@Column(columnDefinition="uuid")と注釈を付けます。

+0

これには何の不運もありません。 @Converterアノテーションはクラスには適用されません。 – ruckc

+0

何を意味するのかよく分かりません。 javax.persistence.Converterとorg.eclipse.persistence.annotations.Converterの両方をクラスに適用できます。私は答えを編集して、javax.persistence.Converterを使用していることを明示しました。 –

+0

それは働いた(PG9.4) - また@Columnアノテーションは私のために必要ではありません。 – Jack

1

Olegによって提案されたソリューションは、私にとっては完璧に機能しませんでした(ヌル値を維持しようとすると失敗しました)。ここでは、null値に対しても機能する調整されたソリューションがあります。

私の場合は、EclipseLinkを使用していますが、Hibernateを使用している場合は、これは必要ありません。 PostgresqlのJDBCドライバの

public class UuidConverter implements AttributeConverter<UUID, Object> { 
    @Override 
    public Object convertToDatabaseColumn(UUID uuid) { 
     PGobject object = new PGobject(); 
     object.setType("uuid"); 
     try { 
      if (uuid == null) { 
       object.setValue(null); 
      } else { 
       object.setValue(uuid.toString()); 
      } 
     } catch (SQLException e) { 
      throw new IllegalArgumentException("Error when creating Postgres uuid", e); 
     } 
     return object; 
    } 

    @Override 
    public UUID convertToEntityAttribute(Object dbData) { 
     return (UUID) dbData; 
    } 
} 
2

新しいバージョン>= 8.4-701正しくjava.util.UUIDマッピングを扱います。そして、Hibernate >= 4.3.xも同様です。

https://stackoverflow.com/a/780922/173149の詳細を参照してください:

Map the database uuid type to java.util.UUID. 
This only works for relatively new server (8.3) and JDK (1.5) versions. 
5

が、それはHibernateの5.1.xのでの作業持っているために、あなたはスティーブ・エバーソールcomment here

@Id 
@GeneratedValue 
@Column(columnDefinition = "uuid", updatable = false) 
public UUID getId() { 
    return id; 
} 
+0

できれば私はこの答えのために二度声を出します。 columnDefinition仕様では、テーブル作成時にUUIDがジオメトリタイプに置き換えられたときの問題が解決しました。 PostgisDialectが使用されたために起こったことです。 –

0

は、PostgreSQLのURL接続にこのフラグを追加します従うことができます:?stringtype =不特定

このように

jdbc:postgresql:// localhost:5432/yourdatabase?stringtype = unspecified

+0

これは疑問に答えるかもしれませんが、答えの本質的な部分とOPコードの問題点について説明する方がよいでしょう。 – pirho

関連する問題