現在、レガシーデータベース(多数の複合キーだけでなく、単一列キー)のJPAエンティティを定義しています。その後、JPA(Hibernate):ジェネリック@MappedSuperclassで@EmbeddedIdを使用するとエラーが発生する
@MappedSuperclass
public abstract class AbstractEntity<ID extends Serializable> {
public abstract ID getId();
public abstract void setId(ID id);
}
そして、複合キーのスーパークラス(だけでなく、長い間、主キーのスーパークラスではなく、ここに記載されている):
@MappedSuperclass
public abstract class AbstractEmbeddedIdEntity<ID extends Serializable> extends AbstractEntity<ID> {
@EmbeddedId
private ID id;
public AbstractEmbeddedIdEntity() {
id = newId();
}
@Override
public ID getId() {
return id;
}
@Override
public void setId(ID id) {
this.id = id;
}
protected abstract ID newId();
}
そして最後に、具体的な実体のような私には、次のエンティティのスーパークラスを作成しましたこの:
@Entity
@Table(name = "firstEntity")
public class FirstEntity extends AbstractEmbeddedIdEntity<FirstEntityId> {
public FirstEntity() {
}
@Embeddable
public static class FirstEntityId implements Serializable {
@Column(name = "firstId")
private String firstId;
public FirstEntityId() {
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof FirstEntityId)) {
return false;
}
FirstEntityId other = (FirstEntityId) obj;
return
Objects.equals(firstId, other.firstId);
}
@Override
public int hashCode() {
return Objects.hash(firstId);
}
}
@Override
protected FirstEntityId newId() {
return new FirstEntityId();
}
}
今の問題は、私はこのような複数のエンティティを持っているとエンティティのIDプロパティにアクセスしようとした場合(現在は春ブーツ、例えばとということです)、例外がスローされます。
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [firstId] on this ManagedType [unknown]
私はこれをデバッグし、休止状態で、メタモデルは、同じMappedSupperclassインスタンスに私のエンティティのすべてをマップすることを見出しました。アプリケーションの起動時に、newId()
によって返された@EmbeddedId
はMappedSupperクラスに設定され、は前のエンティティのIDであるを上書きします。結局、すべてのエンティティは同じMappedSupperクラスにマッピングされますが、MappedSupperクラスは最後のエンティティの@EmbeddedId
しか持ちません。
上記の例では、最後のエンティティの@EmbeddedId
には "firstId"というプロパティがありません(最後のエンティティのIDプロパティで上書きされているため)、IDプロパティへのアクセスは失敗します。
私は何か不足している場合や、これが休止状態で問題になる可能性がある場合、私のアプローチが間違っているのだろうかと思います。
スプリングブートavailable on githubを使った完全な例。 mvn spring-boot:run
で実行してください。
JPA/Hibernateマッピングに関して、抽象クラスを使用しない方が良いと思います。ただし、スーパークラスの継承意味ではありません。実際には、 '@ MappedSuperclass'は継承のために使用されるため、それを拡張する異なるクラス間の巨大なリンクを意味します。 最も簡単な方法でそれらを1つずつマップするべきです。そのため、それらは 'AbstractEntity'クラスとは関係ありません。 – DamCx
「私のすべてのエンティティがそのMappedSupperクラスの同じインスタンスを指している」ということはどういう意味ですか? Javaには、共通のスーパークラスオブジェクトへのポインタはありません。また、私があなたの場合は、内部クラスを組み込み可能ファイルとして使用しないでください。 – crizzis
@crizzis:私は質問を更新し、間違った部分を修正しました。実際、ハイバネートメタモデルは、すべてのエンティティを同じMappedSupperclassインスタンスにマップします。また、埋め込み可能なクラスとして内部クラスを使用することを避けるのはなぜですか? – Dominic