2009-06-11 12 views
10

これはHibnerate多型質問とデータモデル設計です 質問です。彼らは絡み合っている。私は過去にHibernateを使っていましたが、 を楽しんだことがありますが、時には些細なこと以外にも と考えるのは難しいと感じることがあります。 Hibernateのノックではありません。ただ ORMが一般的に挑戦的であるという観察。Hibernate多型

これはHibernate 101の質問ですが、わかりません。私が達成しようとしていることは、不可能かもしれません。

私はアップル とオレンジにサブクラス化される抽象クラスフルーツを持っています。私はノートやコメントを表すノートクラスを持っています りんごとオレンジについて。アップルまたはオレンジには多くのノート が関連付けられていますが、特定のノートに関連付けられているAppleまたはオレンジは になります。

ここでは、ここではオブジェクトIDの移動先の と、それらを をOrangesと区別するApplesのプロパティを省略しているクラスのスケッチを示します。当分は、私が使用しているHibernateの継承戦略について強く感じることはありません。ここで

abstract public class Fruit { 
} 

// Apples have notes written about them: 
public class Apple extends Fruit { 
    private Set<Note> note; 
    ... 

    @OneToMany(cascade = CascadeType.ALL) 
    public Set<Note> getNote() { 
     return note; 
    } 
} 


// Oranges have notes written about them: 
public class Orange extends Fruit { 
    private Set<Note> note; 
    ... 

    @OneToMany(cascade = CascadeType.ALL) 
    public Set<Note> getNote() { 
     return note; 
    } 
} 

我々はそれがAppleとオレンジの両方のフィールドを持っていることがわかり おり、現在実装されているノートクラスです。この設計上の瑕疵または不調和 は、単一のノートインスタンスがAppleまたはOrangeのいずれか1つを指しているだけであり、両方とも決して指していないということです。ノートが Appleにバインドされている場合、オレンジ色のフィールドは不必要で見苦しいものになり、 viceversaとなります。

// A note about an Apple or Orange 
public class Note { 
    private String theNote; 
    private Apple apple; 
    private Orange orange; 
    ... 

    // with the usual many to one mapping 
    @ManyToOne 
    @JoinColumn(name = "apple_id") 
    public Apple getApple() { 
     return apple; 
    } 

    // with the usual many to one mapping 
    @ManyToOne 
    @JoinColumn(name = "orange_id") 
    public Orange getOrange() { 
     return orange; 
    } 

    ... 
} 

しかし、これは私が私が私の のデザインをベースにする考える注クラスがあるが、私は、注釈とテーブルのマッピングを休止状態に関して でこれを考えるするかどうかはわかりません。

// A note about a fruit: 
public class Note { 
    private String theNote; 
    private Fruit fruit; 
    ... 
} 

ここで、果物はアップルまたはオレンジのインスタンスになります。

この後者のノートクラスは、実際にAppleまたはOrangeを保持するFruitを参照しても、Hibernate ORMマッピングでも調整できますか?はいの場合、誰かがどのように話してもらえますか?

+0

私のコードがMySQLデータベースで実行されているため、同様の問題があります。あなたは私の関連する質問で私を助けてくれるのですか?ここにリンクがあります:http://stackoverflow.com/questions/25252541/generatedvalue-for-a-java-abstract-superclass-over-mysql – CodeMed

答えて

13

これは絶対に可能です。あなたは、実装の各でそれらを繰り返すのではなく、抽象Fruitクラスにノートを関連付けることができます:

@Entity 
@Inheritance 
public abstract class Fruit { 
    private Set<Note> notes; 
    ... 

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "fruit") 
    public Set<Note> getNotes() { 
     return notes; 
    } 
} 

@Entity 
public class Apple extends Fruit { 
    ... 
} 


@Entity 
public class Orange extends Fruit { 
    ... 
} 

@Entity 
public class Note { 
    private String theNote; 

    @ManyToOne 
    private Fruit fruit; 
    ... 
} 

ら出来上がり!

- コメントに基づいて追加: JPAでは、継承を処理するための複数の戦略を提供しています。 relevant section in the Java EE tutorialはあなたが始めるのを助けるはずです。

は基本的に、あなたのオプションは次のとおりです。

  • 1つのテーブル内のすべてを保存し、どのタイプ
  • 別のテーブルに各具象クラス(アップルとオレンジ)を格納している行を知っている識別子列を使用して
  • フルーツテーブル

への外部キーと共通の識別子列とフルーツテーブル、およびアップルとオレンジのテーブルを持つ

  • 別の編集: これはJPAの質問ではなく、Hibernateであることに気付きました。しかし、オプションが同じであれば、それほど大きな違いはありません。ここにはrelevant section in the Hibernate docsがあります。

  • +0

    一時的な-1:これは質問に答えるのではありませんか?あなたは、フルーツとノートとの関係について、ハイバーネイトに話しました。フルーツをアップルまたはオレンジのどれかにあいまいにする方法をどのように伝えますか? –

    +1

    @ Jason:実際はそうですし、文字通りです。質問をもう一度読むと、特に最後の段落が2番目のコードブロックから始まり、私が提供しているコードは、ae6rtが求めているコードとまったく同じです。 – Henning

    +0

    -1が削除されました...アップルがオレンジとは異なる方法でデータベースに保存される方法について詳しく説明できますか? –

    4

    このパターンは、Hibernateベースのデータレイヤーでは非常に一般的です。内部的にどのように動作するかは、継承戦略が使用されているかどうかに大きく依存します。

    クラスごとまたはテーブルごとに継承を使用する場合、すべてのサブクラス/クラスのテーブルが作成されます。たとえば、あなたのケースでは、テーブルFruitと2つのテーブルAppleOrangeがあり、FruitとApple/Orangeの間の外部キー参照があります。 1つのフルーツ(リンゴかオレンジか)をIDで要求する場合、HibernateはFruitテーブルをAppleテーブルとOrangeテーブルで外側に結合します。各行は、フィールドが検索されたテーブルに応じてAppleまたはOrangeに変換されます。

    また、ディスクリミネータを使用することもできます。識別子フィールド(例:appleおよびorangeを取るfruit_type)を含む単一のテーブルFruitが使用されます。このフィールドの値に応じて、Hibernateは対応するオブジェクトがアップルかオレンジかを判断します。

    あなたのケースでは、熱心な読み込みの場合、HibernateがNoteオブジェクトを読み込むときに、対応するFruitを熱心に取得し、それに応じてAppleまたはOrangeのインスタンスで果物フィールドを設定します。

    レイジーフェッチの場合、フルーツフィールドはフルーツインターフェイスを実装するプロキシになります。実際のフルーツフィールドがロードされるまで、そのタイプは不定です。

    これは、あなたの質問のいくつかにお答えしたいと考えています。