2017-08-29 15 views
4

現在、レガシーデータベース(多数の複合キーだけでなく、単一列キー)の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で実行してください。

+0

JPA/Hibernateマッピングに関して、抽象クラスを使用しない方が良いと思います。ただし、スーパークラスの継承意味ではありません。実際には、 '@ MappedSuperclass'は継承のために使用されるため、それを拡張する異なるクラス間の巨大なリンクを意味します。 最も簡単な方法でそれらを1つずつマップするべきです。そのため、それらは 'AbstractEntity'クラスとは関係ありません。 – DamCx

+0

「私のすべてのエンティティがそのMappedSupperクラスの同じインスタンスを指している」ということはどういう意味ですか? Javaには、共通のスーパークラスオブジェクトへのポインタはありません。また、私があなたの場合は、内部クラスを組み込み可能ファイルとして使用しないでください。 – crizzis

+0

@crizzis:私は質問を更新し、間違った部分を修正しました。実際、ハイバネートメタモデルは、すべてのエンティティを同じMappedSupperclassインスタンスにマップします。また、埋め込み可能なクラスとして内部クラスを使用することを避けるのはなぜですか? – Dominic

答えて

0

これは私には休止状態のバグのように見えるので、hibernate bug trackerのチケットを作成しました。 回避策として、抽象スーパークラスの代わりに具体的なエンティティクラスにID属性(@EmbeddedId)を定義します。

関連する問題