3

示されているテーブルスキーマにJPAクラスを構築しているときに発生するエラーが含まれています...このエラーを解決する方法を誰かに教えてもらえますか?また、キーの1つが実際に外部キーである場合の複合キーの作成方法。私の注釈の何が問題になっていますか?

エラー

org.apache.openjpa.util.MetaDataException:タイプ「classSpecialty」で指定されたidクラスが、クラスの主キーフィールドと一致しません。
IDクラスに、pkフィールドタイプを含む永続タイプと同じ主キーがあることを確認してください。不一致のプロパティ: "personId"

テーブルスキーマ

テーブルLocation(を作成します
  id int主キー、
  シティvarchar(255)、
  状態varchar(100)、
  国varchar(255)
);
テーブルPerson(を作成します
  id int主キー、
  名前varchar(100)
);
テーブルを作成するフォトグラファー(
  id int主キーはPerson(id)を更新カスケードで削除カスケードで参照します。
  LivesIn int not null参照Location(id)on updatecascade on delete no action
);
テーブルSpecialty(を作成します
  フォトグラファーintは、カスケードの削除の更新カスケードでフォトグラファー(id)を参照します。
  タイプenum('portrait'、'landscape'、'sport')、
  主キー(写真家、タイプ)
);
テーブルの作成Photo(
  id int主キー、
  takeAtタイムスタンプがnullではない、
  TakenBy intは、アクションなしの削除時の更新カスケードでフォトグラファー(id)を参照します。
  photosedAt intは、アクションなしの削除時の更新カスケードのLocation(id)を参照します。
  タイプenum('portrait'、'landscape'、'sport')
);
テーブルの外観を作成します(
  削除カスケードでの更新カスケードでのint参照Person(id)を示します。
  isShownIn intは、カスケードの削除時にカスケードを更新するときにPhoto(id)を参照します。
  主キー(shows、isShownIn)
);

クラス

Person.java

@実在物
パブリッククラスPersonはSerializableを実装します{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    プライベート文字列名。


Location.java

@実在物
パブリッククラスLocationはSerializable{を実装します

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    プライベートストリングシティ;

    プライベート文字列状態。

    プライベート文字列の国;


Photographer.java

@実在物
パブリッククラスのフォトグラファーはSerializableを実装します{

    @Id
    @ManyToOne
    @Column(name = "id")
    プライベートパーソンpersonId;

    @ManyToOne
    @Column(name = "livesIn")
    プライベートロケーションlivesIn;

Photo.java

@実在物
パブリッククラスの写真はSerializableを実装します{

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    // 外部キー
    @ManyToOne
    @JoinColumn(name = "takenBy")
    プライベートフォトグラファーtakenBy;

    // 外部キー
    @ManyToOne
    @JoinColumn(name = "photographedAt")
    プライベートロケーションphotographedAt;

    @Basic(オプション= false)
    @Column(name = "takenAt"、insertable = false、updatable = false)
    @Temporal(TemporalType.DATE)
    プライベート撮影日;

    @ Enumerated(EnumType.STRING)
    プライベートPhotoTypeタイプ。

PhotoType

 
public enum PhotoType {
    PORTRAIT( "portrait")、LANDSCAPE( "landscape")、SPORT( "sport");
    プライベート文字列型。

    PhotoType(文字列型){
        this.type = type;
    }

    public String getType(){
        リターンタイプ;
    }

}

Specialty.java

 
インポートjava.io.Serializable;

インポートjavax.persistence.Column;
インポートjavax.persistence.Embeddable;
インポートjavax.persistence.EmbeddedId;
インポートjavax.persistence.Entity;
インポートjavax.persistence.EnumType;
インポートjavax.persistence.Enumerated;
インポートjavax.persistence.Id;
インポートjavax.persistence.JoinColumn;
インポートjavax.persistence.ManyToOne;
インポートjavax.persistence.OneToMany;
インポートjavax.persistence.OneToOne;

@実在物
パブリッククラスSpecialtyはSerializableを実装します{

    @EmbeddedId
    保護されたSpecialtyPKspecialtyPK;

    public Specialty(){
        素晴らしい();
    }

    public Specialty(SpecialtyPK specialtyPK){
        素晴らしい();
        this.specialtyPK = specialtyPK;
    }

}

@Embeddable
クラスSpecialtyPKはSerializableを実装します{

    @ManyToOne
    @Column(name = "id")
    プライベートフォトグラファーpersonId;

    @ Enumerated(EnumType.STRING)
    プライベートPhotoTypeタイプ。

    / *
     *(Javadoc以外)
     *
     * @see java.lang.Object#hashCode()
     * /
    @オーバーライド
    public int hashCode(){
        最終的なintプライム=31;
        int result = 1;
        結果=プライム*結果
                +((personId == null)?0:personId.hashCode());
        結果=プライム*結果+((type == null)?0:type.hashCode());
        結果を返します。
    }

    / *
     *(Javadoc以外)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     * /
    @オーバーライド
    public boolean equals(Object obj){
        if(this == obj)
            trueを返します。
        if(obj == null)
            falseを返します。
        if(getClass()!= obj.getClass())
            falseを返します。
        SpecialtyPK other =(SpecialtyPK)obj;
        if(personId == null){
            if(other.personId!= null)
                falseを返します。
        } else if(!personId.equals(other.personId))
            falseを返します。
        if(type!= other.type)
            falseを返します。
        trueを返します。
    }

    public SpecialtyPK(){
        素晴らしい();
        //TODO自動生成されたコンストラクタスタブ
    }

    public SpecialtyPK(フォトグラファーpersonId、PhotoTypeタイプ){
        素晴らしい();
        this.personId = personId;
        this.type = type;
    }

}

コンポジットキーでの試行も失敗し、同じエラーが発生しました。

多くのインターネット検索はまだ解決策につながりません。

4

2 に答える 2

1

複合主キーを持っているように見えますが、JPA に、主キーが埋め込まれていることを注釈で伝えています。初めてプロジェクトに参加するすべての人に伝えます。

クライアントのニーズに応じて、効率性と最適化に注意を払うことなく、最も単純な作業を最初に行います。

時期尚早の最適化は、多くのソフトウェアの問題の根源です。

于 2012-11-25T05:21:49.300 に答える
0

問題は2倍です。1 つの問題は、SpecialtyPK 内の personId マッピングにあります。@Column は基本的なマッピングに使用されます。@JoinColumn アノテーションを使用して、結合に使用する列を指定する必要があります。

2 つ目の重要な点は、主キー クラスにリレーションシップを含めないことです。主キー クラスとして定義された埋め込み可能かどうかは関係ありません。基本的なマッピングまたはその他の主キーのみを含める必要があります (派生 ID は JPA 2.0 で許可されています。これは、キー クラスをネストできることを意味します)。そのため、タイプが「int」の personId を持つ SpecialtyPK クラスが必要になります。次に Specialty 内で ManyToOne マッピングを指定し、@MapsId を追加して int を指すようにします。これにより、リレーションシップを設定するだけで済み、embeddable 内の基本的なマッピングを管理する必要がなくなります。

@Entity
public class Specialty implements Serializable {

    @EmbeddedId
    protected SpecialtyPK specialtyPK;

    @MapsId("personId")
    protected Photographer photographer;
..

class SpecialtyPK implements Serializable {

    @Column(name = "id")
    private int personId;//defaults to basic

..

または、embeddedId を削除して、写真家を ID としてマークすることもできます。

于 2012-11-26T15:52:01.817 に答える