web-dev-qa-db-ja.com

JPAを使用したPostgreSQLでのUUIDの永続化

UUIDを主キーとして使用するエンティティを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をbyte []として永続化しようとしても役に立たなかった。

@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を削除すると、上記のエラーと同じエラーが発生します。しかし、@ 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

こんな簡単なことはできないのでとても気分が悪いです!

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

SO同じ問題について多かれ少なかれ多くの質問を見てきましたが、それらはすべて古く、どれも簡単な答えを持っているようには見えません。

醜いハックに頼ることなく、これを標準的な方法で実現したいと思います。しかし、これが(醜い)ハックでしか達成できない場合は、それが私がやることです。ただし、UUIDをデータベースにvarcharとして保存したくないので、パフォーマンスは良くありません。また、可能であれば、コードにHibernate依存関係を導入しないようにします。

どんな助けでも大歓迎です。

更新1(2012-07-03 12:15 pm)

さて、まあ、まあ... JTDSドライバー(v1.2.5)を使用してSQLサーバー2008 R2でまったく同じコード(プレーンUUID、変換なし-上記のコードの最初のバージョン)をテストしたことは、ちょっと興味深いです。 、何だと思いますか、それは魅力として機能しました(もちろん、persistence.xmlで接続関連の情報を変更する必要がありました)。

さて、それはPostgreSQL固有の問題ですか、それとも何ですか?

27
ehsanullahjan

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タイプマッピングとして登録することです。これはドキュメント@ http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch06.html#types-registry でカバーされています

33
Steve Ebersole

JPA 2.1は、PostgreSQLのuuid列タイプと、対応するエンティティフィールドのタイプとして_Java.util.UUID_を使用する非常に簡単な方法を提供します。

_@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;
    }

}
_

このクラスを永続化設定に追加し、UUIDフィールドに@Column(columnDefinition="uuid")で注釈を付けます。

16
Oleg Estekhin

Hibernate 5.1.xで動作させるには、Steve Ebersoleをフォローする ここにコメント

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

新しいバージョン>= 8.4-701のPostgresql JDBCドライバが正しく処理されますJava.util.UUIDマッピング。そして、休止状態>= 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.
3
gavenkoa

Olegによって提案された解決策は私には完全に機能しませんでした(null値を永続化しようとすると失敗しました)。これは、null値に対しても機能する微調整されたソリューションです。

私の場合、私はEclipseLinkを使用していますが、Hibernateを使用している場合、これは必要ないかもしれません。

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;
    }
}
1
Ixim

このフラグをpostgresql url接続に追加します:?stringtype = unspecified

そのように

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

0
user8157076