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固有の問題ですか、それとも何ですか?
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 でカバーされています
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")
で注釈を付けます。
Hibernate 5.1.xで動作させるには、Steve Ebersoleをフォローする ここにコメント
@Id
@GeneratedValue
@Column( columnDefinition = "uuid", updatable = false )
public UUID getId() {
return id;
}
新しいバージョン>= 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.
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;
}
}
このフラグをpostgresql url接続に追加します:?stringtype = unspecified
そのように
jdbc:postgresql:// localhost:5432/yourdatabase?stringtype = unspecified