JPA を使用して、主キーが「データの char(16) ビット」として定義された列に格納された UUID である DB2 データベースのテーブルにレコードを読み書きする必要があります。
データはビット形式でデータベースに格納されるため、列を JPA エンティティ クラス内の文字列として扱うことができません。少しグーグルした後、JPA と UUID の主キーでこの Web ページを見つけ、コードで @Id アノテーションを使用してバイト配列データ型を使用しようとしましたが、コードを実行すると、次のエラー メッセージが表示されて失敗しました。
型 "class model.AbstractEntity" はフィールド "id" を主キーとして宣言していますが、型 "[B" のキーはサポートされていません。
JPA 標準を見ると、バイト配列は主キーとしてサポートされていないようです。
私が書いているコードは、コンテナーによって提供される OpenJPA を使用して、WebSphere 8.5 で実行される EJB の一部です。残念ながら、データベース スキーマを変更することはできません。
だから私の質問は、データベースの主キーを含む列が「データのchar(16)ビット」として定義されている場合、どのJavaデータ型を使用する必要があるJPAエンティティクラスにありますか?
私はすでにこれらのSOの質問を見てきましたが、私が抱えている問題には役に立ちません。
更新 @Rick の提案に基づいて、主キーに使用されるバイト配列を含む ID クラスを作成しました。ただし、レコードをテーブルに永続化しようとすると、DB2 はエラーを返します。
Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: The value of input variable, expression or parameter number "1" cannot be used because of its data type.. SQLCODE=-301, SQLSTATE=07006, DRIVER=3.63.123 {prepstmnt -937290353 INSERT INTO FRAMEWORK.SITE3 (ID, SITE_ADDRESS, SITE_NAME, ROW_VERSION) VALUES (?, ?, ?, ?) [params=(InputStream) java.io.ByteArrayInputStream@94c7f78e, (String) test, (String) test, (int) 1]} [code=-301, state=07006]
ID クラスのコードは次のとおりです。
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.UUID;
import javax.persistence.Embeddable;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
@Embeddable
@Access(AccessType.FIELD)
public class UniqueId implements Serializable {
private static final long serialVersionUID = 4458438725376203754L;
@Column(name="ID")
private byte[] id;
public UniqueId() {}
public UniqueId(byte[] id) {
this.id = id;
}
public UniqueId(String id) {
this(toByteArray(UUID.fromString(id)));
}
@Override
public String toString() {
return toUUID(id).toString();
}
public static UniqueId fromString(String s) {
return fromUUID(UUID.fromString(s));
}
public static UniqueId fromUUID(UUID uuid) {
return new UniqueId(toByteArray(uuid));
}
private static byte[] toByteArray(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();
}
private static UUID toUUID(byte[] byteArray) {
long msb = 0;
long lsb = 0;
for (int i = 0; i <8; i++)
msb = (msb << 8) | (byteArray[i] & 0xff);
for (int i = 8; i < 16; i++)
lsb = (lsb << 8) | (byteArray[i] & 0xff);
UUID result = new UUID(msb, lsb);
return result;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(id);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UniqueId other = (UniqueId) obj;
if (!Arrays.equals(id, other.id))
return false;
return true;
}
public static UniqueId generate() {
return fromUUID(UUID.randomUUID());
}
}
ByteArrayInputStream を DB2 が理解できるものに変換するためにクラスに追加する必要のある特定のものはありますか?それとも OpenJPA によって内部的に処理する必要がありますか? OpenJPA のユーザー ガイドを調べましたが、バイト配列の使用に関する情報はほとんどありません。