8

PostgreSQLでの継承と、それをJPAでのエンティティとしてマッピングすることについて質問があります。私たちのデータベースとマップしたいテーブルは次のとおりです。

CREATE TABLE Answer (
    idAnswer SERIAL,
    answerContent VARCHAR,
    idQuestion INTEGER,
    version INTEGER,

    CONSTRAINT Answer_idAnswer_PK PRIMARY KEY (idAnswer),
    CONSTRAINT Answer_idQuestion_FK FOREIGN KEY (idQuestion) REFERENCES Question(idQuestion)
);


CREATE TABLE MatchAnswer (
    matchingAnswer VARCHAR NOT NULL,
    version INTEGER,

    CONSTRAINT MatchAnswer_idAnswer_PK PRIMARY KEY (idAnswer)       
) INHERITS(Answer);


CREATE TABLE TrueFalseAnswer (
    isTrue BOOLEAN NOT NULL,
    version INTEGER,

    CONSTRAINT TrueFalseAnswer_idAnswer_PK PRIMARY KEY (idAnswer)   
) INHERITS(Answer);

そして、Netbeans7.1.2の自動ツールを使用してそれらをエンティティにマッピングしました。最初は追加するだけで十分だと思いました

@Entity
@Table(name = "truefalseanswer", catalog = "jobfairdb", schema = "public")
@XmlRootElement
public class Truefalseanswer extends Answer implements Serializable {
    private static final 

したがって、拡張するだけですが、正しく機能しませんでした。これに対する最善のアプローチは何ですか?前もって感謝します。

4

3 に答える 3

8

JPAの継承の概念は、通常のテーブルに基づいています。PostgreSQLのテーブル継承の概念を実際に「取得」するわけではありません。これは、機能の最小公分母を公開し、移植可能に行うように設計された仕様を使用する場合のコストの1つです。

JPA継承戦略の適切な要約については、このガイドを参照してください。@Inheritance用の新しいJava6JavaDocには、次のような注記があることに注意してください。

継承アノテーションが指定されていない場合、またはエンティティクラス階層に継承タイプが指定されていない場合は、SINGLE_TABLEマッピング戦略が使用されます。

...そして、どのようにSINGLE_TABLE機能するかを見ると、それが機能しないのは当然のことです。すべてのサブクラスが魔法の弁別値を持つ1つの大きなテーブルにあることを期待しています。

InheritanceType.TABLE_PER_CLASSはPgの動作に近いですが、基本型テーブルにリーフ型の各エンティティのエントリがある場合、JPAimplは少し混乱するのではないかと思います。スーパークラスでクエリを実行するときにサブクラステーブル全体でクエリを実行しようとするとUNION、奇妙な結果が生じる可能性があります。少なくとも、を使用すると重複し、UNIONを使用するとパフォーマンスの問題が発生する可能性がありますUNION ALL。プロバイダーが戦略をどのように実装するかに応じて、少なくとも部分的に機能する可能性があります。テストする必要があり、結果はおそらくプロバイダー固有のものになります。

ONLYJPAのPG継承サポートの本当に優れた実装には、継承とクエリのPostgreSQL拡張機能を理解した新しい継承戦略のためのJPAプロバイダー拡張機能が必要になる可能性があります。

SELECT ... FROM ONLY subclass_tableモードのときにJPA実装を使用するように説得できればInheritanceType.TABLE_PER_CLASS、PostgreSQLの継承と相互運用できるはずです。各テーブルの継承されていない行のみが表示され、通常のテーブルであるかのように処理されます。その後、他の非JPAコードは、継承機能を引き続き使用できます。HibernateのPostgreSQLダイアレクトコードを変更してこれを行うことは可能だと思いますが、継承に大きく依存する既存のPostgreSQLスキーマをJPAでサポートする必要がない限り、個人的にはそこに行きません。

于 2012-08-07T08:41:01.310 に答える
3

MappedSuperClassアノテーションを使用する解決策があります。

@MappedSuperClass
public abstract class AbstractAnswer{
    @Id
    protected Long idAnswer;

    @Column(name="answerContent")
    protected String answerContent;
}

@Entity
@Table(name="Answer")
public class Answer extends AbstractAnswer{

}

@Entity
@Table(name="MatchAnswer")
public class MatchAnswer extends AbstractAnswer{
    protected String matchingAnswer;
}

@Entity
@Table(name="TrueFalseAnswer")
public class TrueFalseAnswer extends AbstractAnswer{
    protected Boolean trueFalseAnswer;
}
于 2015-11-03T02:09:02.553 に答える
2

Hibernateの継承は、PostgreSQLの継承とは何の関係もありませんが、どちらも同じことを達成しようとし、同じように見える場合があります。

これは、HibernateがSQL標準をベースとして採用し、各RDBMSの小さな特定の機能を調整するためです。たとえば、MySQLにはシーケンシャルIDの「自動インクリメント」がありますが、Oracleはシーケンスを使用します。

歴史的に、データの継承(または特殊化)は、特定のフィールドに個別のテーブルを使用して行われ、primary-foreign-keysがテーブルをリンクしていました。あなたの例では、MatchAnswerはAnswer.idAnswerに対してPKおよびFKとしてIDを持っています。TrueFalseAnswerと同じです(IDはAnswer.idAnswerに対するPK / FKです)。

あなたが投稿した「継承」定義はどのSQL標準でも(AFAIK)定義されていないので、Hibernateがこれをサポートしているとしたら、特にPostgreSQLに非常に固有のようで、やや実験的な機能のように見えるので、驚きます。 :PostgreSQLドキュメントの「継承」の章にある「警告」を参照してください。

とは言うものの、データを正気に保ち、リレーショナルモデルのベストプラクティスに従ってマッピングすることをお勧めします。次に、Hibernateマッピングで、意味のある場所でデータ継承を表現できます。

于 2012-08-07T08:39:48.927 に答える