5

ポリモーフィック アソシエーションは、外部キーまたは多対 1 の関係に似ていますが、ターゲットが多くのタイプ (言語のクラス、データベースのテーブル) のいずれかであるという違いがあります。

数年間使用してきたデータベース設計を PHP から Java に移植しています。古いコードでは、独自の ORM を展開していましたが、これは多くの理由で最適ではありませんでした。後で微調整を開始し、自分で再度実装することになるかもしれませんが、今のところ、エンティティ クラスで市販の ORM と JPA を使用したいと考えています。

データベースのレイアウトについて、JPA で表現する方法がわからないことが 1 つあります。

Nodeグラフを格納するテーブルがEdgeあります(重要な場合はDAG)。各ノードは、必要に応じて、データベースから別のエンティティを 1 つ参照できます。これらのエンティティは、グラフ全体で複数回参照される可能性があり、ユーザーがアクセスできない「孤立した」エンティティも存在する可能性がありますが、少なくともしばらくの間保持することは理にかなっています。

これらのオブジェクトは、継承などの点でまったく関連していませんが、Customer->Site->Floor->Room のような自然な階層を持っています。実際、何年も前に、「親」オブジェクトを指す外部キー フィールドだけから始めました。しかし、この階層は十分に柔軟ではなく、バラバラになり始めました。

たとえば、ユーザーがフォルダー内のオブジェクトをグループ化できるようにしたいのですが、一部のオブジェクトは複数の「親」を持つことができ、時間の経過とともに関係が変化します。以前の関係を追跡する必要があるため、グラフのエッジにはタイムスパンが関連付けられており、そのエッジがいつからいつまで有効であったかが示されます。

ノードからオブジェクトへのリンクは、ノード テーブルの 2 つの列に格納されます。1 つは外部テーブルの ID を保持し、もう 1 つはその名前を保持します。例 (一部の列は省略):

table Node:
+--------+-------+----------+
| ixNode | ixRef | sRefType |
+--------+-------+----------+
|    1   |  NULL |   NULL   |  <-- this is what a "folder" would look like
|    2   |   17  |  Source  |
|    3   |   58  |  Series  |  <-- there's seven types of related objects so far
+--------+-------+----------+

table Source (excerpt):
+----------+--------------------+
| ixSource |        sName       |
+----------+--------------------+
|    16    | 4th floor breaker  |
|    17    | 5th floor breaker  |
|    18    | 6th floor breaker  |
+----------+--------------------+

JPAを使用する以外の解決策があるかもしれません。テーブルのレイアウトを変更したり、新しいテーブルを導入したりすることもできます。ただし、これについてはすでによく考えており、テーブルの構造は問題ないように思えます。思いもよらなかった第3の方法もあるかもしれません。

4

4 に答える 4

5

答えは次のようになります。

  • 継承(Mikeによってすでに提案されているように)
  • プラス@DiscriminatorColumnは、どのサブクラスを使用する必要があるかについての情報を格納する列に関する情報を提供します: sxRef。私が見る唯一の疑いは、「sxRef」がnull許容列であることです。禁止だと思います。
于 2009-07-03T12:51:21.270 に答える
5

すでに答えが出ていると思います。抽象クラス (@Entity または @MappedSuperclass のいずれか) を作成し、さまざまなタイプにそれを拡張させます。

このようなものがうまくいくかもしれません

@MappedSuperclass
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Edge { 
    // . . .
    @OneToMany
    Collection<Node> nodes; 
}

@Entity 
public class Source extends Edge { 
}

@Entity public class Series extends Edge { 
}

@Entity
public class Node { 
    // . . .
    @ManyToOne
    Edge edge; 
}

ソースとシリーズの間の関係を暗示したくないかもしれないことは理解していますが、共通の抽象 (テーブルのない) クラスを拡張することが、あなたが望むことを行うために私が考えることができる唯一の方法です。

InheritanceType.TABLE_PER_CLASS は、ソースとシリーズを別々のテーブルに保持します (SINGLE_TABLE を使用して、前の回答のようなことを行うことができます)。

これが探しているものではない場合、多くの JPA プロバイダーは、既存の一連のテーブルに基づいてマッピングを作成するツールを提供しています。OpenJPA では、ReverseMappingTool [1] と呼ばれます。このツールは、マッピングの開始点として使用できる Java ソース ファイルを生成します。Hibernate や EclipseLink にも似たようなものがあると思いますが、OpenJPA のものを使用して、別のプロバイダーでエンティティー定義を使用することができます (私が知る限り、このツールは OpenJPA 固有のコードを生成しません)。

[1] http://openjpa.apache.org/builds/latest/docs/manual/manual.html#ref_guide_pc_reverse

于 2009-06-30T02:27:17.200 に答える
2

@Anyアノテーションを見ましたか? これは JPA の一部ではありませんが、JPA の Hibernate Annotation 拡張です。

于 2009-06-30T04:38:05.023 に答える
0

ソース テーブルとシリーズ テーブルにはどのくらいの情報が格納されていますか? 名前だけですか?その場合は、それらを 1 つのテーブルに結合し、「タイプ」列を追加できます。Node テーブルの sRefType が失われ、次のような新しいテーブルが作成されます。

ixSource        sName                  sType
  16            4th floor breaker      SOURCE
  17            5th floor breaker      SOURCE
  18            6th floor breaker      SOURCE
  19            1st floor widget       SERIES
  20            2nd floor widget       SERIES

このテーブルは、ソース テーブルとシリーズ テーブルを置き換えます。ソースとシリーズは両方ともスーパークラスに属していますか? それは、このテーブルの自然な名前です。

于 2009-06-26T16:00:50.923 に答える