2008-09-01 17 views
5
@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
public class Problem { 
    @ManyToOne 
    private Person person; 
} 

@Entity 
@DiscriminatorValue("UP") 
public class UglyProblem extends Problem {} 

@Entity 
public class Person { 
    @OneToMany(mappedBy="person") 
    private List<UglyProblem> problems; 
} 

私がしようとしていることはかなり明確だと思います。私は@ManyToOneの人がUglyProblemクラスによって継承されることを期待しています。しかし、次のような例外があります。「UglyProblemクラス(mappedBy = "person")にはこのようなプロパティはありません。@OneToManyがHibernateの継承で動作しない理由

私が見つけたのはthisです。私はエマニュエル・バーナードがこの背後に理由を説明したポストを見つけることができませんでした。


残念ながら、Hibernateのマニュアルに従って「@MappedSuperclassが無視されるよう、スーパークラスからプロパティマッピングされていません。」

まあ、私はこれは私がこの2つのクラスがあればということだと思う:

public class A { 
    private int foo; 
} 

@Entity 
public class B extens A { 
} 

をそのフィールドfooは理にかなっているクラスBのためにマップされることはありません。私はこのようなものがあればしかし:

@Entity 
public class Problem { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

private String name; 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 
} 

@Entity 
public class UglyProblem extends Problem { 

private int levelOfUgliness; 

public int getLevelOfUgliness() { 
    return levelOfUgliness; 
} 

public void setLevelOfUgliness(int levelOfUgliness) { 
    this.levelOfUgliness = levelOfUgliness; 
} 
} 

を私はクラスUglyProblemがfileds idnameと同じテーブルを使用してマッピングする両方のクラスを持っていることを期待しています。 (実際、これはまさに何が起こるか、私はもう一度チェックした)。私はこのテーブルを持っている:私は@ManyToOne人はUglyProblemクラスによって継承されることを期待

CREATE TABLE "problem" (
    "DTYPE" varchar(31) NOT NULL, 
    "id" bigint(20) NOT NULL auto_increment, 
    "name" varchar(255) default NULL, 
    "levelOfUgliness" int(11) default NULL, 
    PRIMARY KEY ("id") 
) AUTO_INCREMENT=2; 

は戻って私の質問に行きます。

他のすべてのマップされたフィールドが継承されているため、ManyToOne関係に対してこの例外を作成する理由はありません。


ええ、私はそれを見ました。実際、私は私のケースでは読み取り専用ソリューションを使用しました。しかし、私の質問は「なぜ...」でしたか?私は、休止状態のメンバーの説明があることを知っています。私はそれを見つけることができませんでした、それが私が尋ねた理由です。

私はこの意思決定の動機づけを知りたいと思います。

(私がこの問題にどのように直面しているか興味があれば、私はHibernate 3を使ってビルドされたプロジェクトを継承しました)Jboss 4.0.something + hibernateは既にそこにありました。 JBossの4.2.2に、私は「@OneToMany mappedBy」の継承されたマッピングがあることを発見し、それが古い設定にうまく働いた...)

+0

あなたは9月4日に、あなたの編集の詳細を追加する必要があります。以前はPersonを問題のリストにマッピングしたいと思っていたと思っていたと思うので、@OneToMany(mappedBy = "person")マッピングのリストだけでなくリストを指定すると、問題の性質が変わります(Ugl –

答えて

4

私はそれがHibernateチームによって作られた賢明な決定だと思います。彼らはそれほど傲慢ではないかもしれませんし、なぜこのように実装されたのかを明確にすることもできますが、Emmanuel、Chris、Gavinの仕組みだけです。 :)

問題を理解しようとしましょう。あなたのコンセプトは「嘘つき」だと思います。あなたは多くのことを言うと問題に関連付けられています。しかし、あなたはそれがが多く、UglyProblem(多くの場合、問題)とは関係がないと言っています。そのデザインに何か問題があります。

データベースへのマッピング方法を想像してみてください。あなたはそう、単一テーブル継承を持っている:

  _____________ 
      |__PROBLEMS__|   |__PEOPLE__| 
      |id <PK>  |   |   | 
      |person <FK> | -------->|   | 
      |problemType |   |_________ | 
      -------------- 

はどのように休止状態は、そのproblemTypeが等しいUPであれば問題だけ人々に関連するためにデータベースを強制するために起こっていますか?それは解決するのが非常に難しい問題です。したがって、このような関係が必要な場合は、すべてのサブクラスがそれ自身のテーブルになければなりません。それは何ですか@MappedSuperclassはそうです。

PS:醜い描画のため申し訳ありません:D

1

私はあなたがとあなたの問題スーパークラスに注釈を付ける必要があると思います@MappedSuperclassの代わりに @Entityです。

4

残念ながら、Hibernate documentationによると、 "@MappedSuperclassとしてマップされていないスーパークラスからのプロパティは無視されます。"私はこれに対しても走った。私の解決策は、エンティティBean自体ではなく、インタフェースを介して望ましい継承を表現することでした。あなたのコードが使用している場合は追加の利点として

@MappedSuperclass 
public abstract class AbstractProblemImpl implements Problem { 
    @ManyToOne 
    private Person person; 

    public Person getPerson() { 
     return person; 
    } 
} 

@Entity 
public class ProblemImpl extends AbstractProblemImpl implements Problem { 
} 

@Entity 
public class UglyProblemImpl extends AbstractProblemImpl implements UglyProblem { 
} 

、:そして、

public interface Problem { 
    public Person getPerson(); 
} 

public interface UglyProblem extends Problem { 
} 

抽象スーパークラスと2つのエンティティのサブクラスを使用して、これらのインタフェースを実装します。あなたの場合

は、次のように定義することができこれらのインタフェースを実装する実際のエンティティBeanではなくインタフェースを使用するため、後でマッピングすることで互換性を損なう可能性が少なくなります。

0

私はOneToMany mappedByの問題を行う方法を考え出しました。

元の投稿の派生クラスUglyProblemにあります。コールバックメソッドは、親クラスではなく、派生クラス内にある必要があります。

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@ForceDiscriminator 
public class Problem { 

} 

@Entity 
@DiscriminatorValue("UP") 
public class UglyProblem extends Problem { 
    @ManyToOne 
    private Person person; 
} 

@Entity 
public class Person { 
    @OneToMany(mappedBy="person") 
    private List<UglyProblem> problems; 
} 

少なくともHibernateを使用する秘密のソースが見つかりました。 http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html @ForceDiscriminatorは、@OneToManyを識別器に使用します。

Hibernate注釈が必要です。

5

私の場合、SINGLE_TABLEの継承型を使用したかったので、@MappedSuperclassを使用することはオプションではありませんでした。

、非常にきれいではないが、クエリでタイプを強制的に@OneToMany協会にHibernateは独自の@Where句を追加するためにどのような作品です:

@OneToMany(mappedBy="person") 
@Where(clause="DTYPE='UP'") 
private List<UglyProblem> problems; 
+0

の代わりに '通常、Eclipse LinkまたはJPAの@ Whereは大いに評価されるでしょう – Odys

+0

HiLink OdLinkでは、何も指定する必要はありません。 Hibernateは通常、oneToManyアノテーションでtargetEntity = Person.classを指定するよう強制します。 フィールド1を持つエンティティUglyPerson uglyPerson;フィールド2 BeutifulPerfoson beutifulPerson; eclipselinkでは、彼は自動的にあなたのBeuftifulPerson @DescriminatorValue( "PRETTY_PERSON")を見て、正しいものをフェッチすることを知っています。Hibernateはこれを知らず、 WHERE句。Eclipselinkはクラスのハイライトを分析し、 eToManyマッピング。 – 99Sono

+0

Ecliipselinkでは、クラス階層の一部であるエンティティがそれぞれ適切なものであることを確認してください。 @DiscriminatorValue( "BEAUTIFUL_PERON")descriminatorとエンティティ場合、基本クラスに何か追加:@DiscriminatorColumnを(名前= "ENTITY_CLASS"、descriminatorType =文字列) 、あなたは簡単にHibernateで @Inheritance(SINGLE_TABLE) を使用することができ、 WHEREクラスを指定し、階層内の各子要素の述部をENTITY_CLASSで継続的に管理する必要があるため、これは非常に難題です。 そこで、ここではeclipselinkが先です。 – 99Sono

関連する問題