2009-09-12 9 views
19

私のjpaドメインモデルに問題があります。私は単純な継承を使い、単純なPersonベースクラスとCustomerサブクラスを使って遊んでいます。公式の文書(JPAとEclipseLinkの両方)によれば、私は基底クラスのID属性/列のみが必要です。 しかし、私はテストを実行するとき、私は顧客が@ Idを持っていないことを私に知らせるエラーをいつも得ますか?JPA継承はサブクラスのIDを要求します

最初は私が最初にプライベートだったので、問題はid属性の可視性にあると思った。しかし、私がprotectedに変更した後でさえ(サブクラスが直接アクセスできるように)、それは働いていません。

パーソン:

@Entity @Table(name="Persons") 
@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(name = "TYPE") 
public class Person { 

    @Id 
    @GeneratedValue 
    protected int id; 
    @Column(nullable = false) 
    protected String firstName; 
    @Column(nullable = false) 
    protected String lastName; 

お客様:

@Entity @Table(name = "Customers") 
@DiscriminatorValue("C") 
public class Customer extends Person { 

    //no id needed here 

は、私が見にアイデアやリソースが不足しています。それはむしろ単純な問題であるはずですが、私はそれを見ていません。

+0

私にも同様の問題があります。 Eclipseと結びついていると思います。私のJBoss開発ツールは、派生したエンティティの欠落している@Idについて苦情を言いますが、Mavenはそれをコンパイルして不平を言っていません。 – Mats

答えて

25

私はすべてのエンティティは、このクラスから継承されMappedSuperclass

@MappedSuperclass 
public abstract class EntityBase{ 
    @Id 
    @GeneratedValue 
    private int id; 

    ...setter/getter 
} 

を作成することによって、それを自分自身を解決しました。私はまだチュートリアルでこれを言及していないのはなぜだろうかと疑問に思っていますが、おそらくJPA 2の実装でうまくいくかもしれません。

+2

+1を使用することができます。私はこれがあなたの特定の質問に対する正解であると信じています。 –

+0

コメントありがとうございます。私はまだそれについて確信していませんでした。 – lostiniceland

+1

これで、oracle-docには、「MappedSuperclass」という注釈があります(https://docs.oracle.com/javaee/7/tutorial/doc/persistence-intro002.htm)。それは間違いなく正しい方法です:) –

3

JPA継承を適用​​するには、2つの異なる方法を知っている:あなたは内の行を区別するために識別子列が必要になります単一テーブル継承で

  • 入社テーブル継承
  • シングルテーブル継承

をテーブル。

結合されたテーブルの継承を使用すると、各クラスは独自のテーブルを取得するので、識別子の列は不要です。

あなたの問題は、2つのコンセプトが混在していることです。だから、次のいずれか

  • は弁別の列を定義し、サブクラス
  • または `InheritanceType.JOINED`が、を使用する上Table` @使用は`が指定されていないしていない `InheritanceType.SINGLE_TABLE`とを使用弁別子の列と値!
+1

私はそれを試しましたが、それと同じ問題です。また、http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Joined.2C_Multiple_Table_Inheritanceによれば、ディスクリミネータ – lostiniceland

4

これは古くても有効ですが、私は知っています。私は同じ問題に遭遇した。ただし、@MappedSuperClassは単一の継承テーブルと同じではありません。 MappedSuperClassは、(私が理解するように)サブクラスごとに別々のテーブルを作成します。

私は正確な理由はわかりませんが、継承されたクラスが1つしかないときは問題はありませんでした。しかし、私は2番目と3番目を追加した後、私は同じエラーが発生しました。私が@Idアノテーションを子テーブルに指定したとき、それは再び働き始めました。

私のレイアウトは簡単でしたが、企業、代理店、クライアントの連絡先情報は簡単でした。

親表:

... 
@Entity 
@Inheritance(strategy= InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="USER_TYPE", length=10, discriminatorType= DiscriminatorType.STRING) 
@Table(name="CONTACTS") 
public abstract class AbstractContact implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    @Column (length=10, nullable=false) 
    protected String mapType; 
    @Column (length=120, nullable=false) 
    protected String mapValue; 
... 

エージェントコンタクト

@Entity 
@DiscriminatorValue("Agent") 
public class AgentContact extends AbstractContact implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="USER_ID") 
    protected Agents agent; 
} 

会社連絡先:

@Entity 
@DiscriminatorValue("Company") 
public class CompanyContact extends AbstractContact implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="USER_ID") 
    protected Companies company; 

} 

クライアントコンタクト:

@Entity 
@DiscriminatorValue("Client") 
public class ClientContact extends AbstractContact implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    protected Long id; 
    //Client table not built yet so... no mapping 
} 

クライアントテーブルはまだ構築されていないので、マッピング情報はありませんが、その点が分かります。

私はMySQLの説明を共有したいと思いますが、Windowsのコマンドプロンプトはカット/コピー/ペーストするにはあまりにも無駄です!本質的には、その: ID(int型PRI) USER_TYPE(VARCHAR(10)) USER_ID(INT) MAPTYPE(VARCHAR(10)) MAPVALUE私はまだセットアップにすべてを持っている

(VARCHAR(120))テストは行っていますが、これまでのところよく見えます(私はすべてのテストをした後に私がこれを忘れることを覚えています)

9

私はまったく同じ問題を抱えていました。サブクラスのために私はなっていた。

Entity class [...] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass.

を私の場合、それは私がpersistence.xmlに私のルートクラスを追加するのを忘れていることが判明しました。

あなたは人と顧客の両方がで定義されていることを確認してください:

<persistence> 
    <persistence-unit> 
    ... 
    <class>package.Person</class> 
    <class>package.Customer</class> 
    ... 
    </persistence-unit> 
</persistence> 
0

Glassfishの/のEclipseLinkを使用している場合、このエラーのために別の理由があるかもしれません:EclipseLinkの< 2.6.0は、ラムダ式とnasty bug原因となったクラスを持っていますそれは無視されます。これは、ここで言及されているような混乱するエラーや他の同様のエラーにつながる可能性があります(たとえば、@Entityアノテーションを持つクラスがエンティティではないことをEclipseLinkから教えてもよい)。

Glassfish 4.1にはEclipseLink 2.5.xが含まれているため、Glassfishを使用している場合、このバグ(および多くの他の多くの問題)があなたを苦しめます。私は4.1.1の代わりにこのバージョンを使用していました。これは、REST Webサービスで検証を使用することが不可能になった別のバグが原因です。あなたの正気を維持したい場合は、Glassfishからできる限り遠くにいてください。

0

エンティティに基づいてデータベーススキーマを生成していない場合、このタイプのエラーが発生することがあります。 その場合は:

は、第一 - あなたのスーパークラスは常に@Id

第二を持っている必要があります - あなたのサブクラスでは、拡張クラス(スーパークラス@Id)

第三を識別し、いくつかの列を持っている必要があります - 上のケースの最も単純な解決策は、対応する外部キー制約を持つ列IDをサブクラステーブルに追加することです。

これが誰かを助けることを願っています! 親指アップ!