33

@AnyAny 関連の注釈 ( 、@AnyMetaDef@AnyMetaDefsおよび) が実際にどのように機能するかを誰かに説明してもらえますか@ManyToAny。これらに関する有用なドキュメントを見つけるのに苦労しています (JavaDoc だけではあまり役に立ちません)。

これまでのところ、抽象クラスと拡張クラスを参照できるようになっていることがわかりました。これが事実である場合、なぜ@OneToAny注釈がないのですか? そして、この「any」は単一の「any」または複数の「any」を指していますか?

短く、実用的で説明的な例は非常に高く評価されます (コンパイルする必要はありません)。

編集:返信を回答として受け入れ、当然のことながら信用を与えたいのと同じくらい、SminkとSakanaの両方の回答が有益であることがわかりました. 複数の返信を回答として受け入れることができないため、残念ながらどちらも回答としてマークしません。

4

4 に答える 4

29

この記事が主題に光をもたらすことを願っています:

共通の祖先エンティティを持たないさまざまなタイプのエンティティに関連付けプロパティをマッピングする必要がある場合があります。そのため、単純なポリモーフィックな関連付けではうまくいきません。

たとえば、メディア ライブラリを管理する 3 つの異なるアプリケーションがあるとします。最初のアプリケーションは本の借り入れを管理し、2 番目のアプリケーションは DVD を管理し、3 番目のアプリケーションは VHS を管理します。アプリケーションに共通点はありません。ここで、3 つのメディア タイプすべてを管理し、既存の Book、DVD、および VHS エンティティを再利用する新しいアプリケーションを開発したいと考えています。Book、DVD、および VHS クラスは異なるアプリケーションに由来するため、祖先エンティティはありません。共通の祖先は java.lang.Object です。それでも、可能なメディア タイプのいずれかを参照できる 1 つの Borrow エンティティが必要です。

このタイプの参照を解決するには、any マッピングを使用できます。このマッピングには常に複数の列が含まれます。1 つの列には、現在マップされているプロパティが参照するエンティティのタイプが含まれ、もう 1 つの列にはエンティティの ID が含まれます。たとえば、書籍を参照する場合、最初の列には次のマーカーが含まれます。 Book エンティティ タイプと 2 番目のエンティティ タイプには、特定の本の ID が含まれます。

@Entity
@Table(name = "BORROW")
public class Borrow{

    @Id
    @GeneratedValue
    private Long id;

    @Any(metaColumn = @Column(name = "ITEM_TYPE"))
    @AnyMetaDef(idType = "long", metaType = "string", 
            metaValues = { 
             @MetaValue(targetEntity = Book.class, value = "B"),
             @MetaValue(targetEntity = VHS.class, value = "V"),
             @MetaValue(targetEntity = DVD.class, value = "D")
       })
    @JoinColumn(name="ITEM_ID")
    private Object item;

     .......
    public Object getItem() {
        return item;
    }

    public void setItem(Object item) {
        this.item = item;
    }

}
于 2008-10-20T09:15:14.690 に答える
24

@Anyアノテーションは、複数のテーブルのクラスへのポリモーフィックな関連付けを定義します。このタイプのマッピングには、常に複数の列が必要です。最初の列は、関連付けられたエンティティのタイプを保持します。残りの列は識別子を保持します。この種の関連付けに外部キー制約を指定することは不可能であるため、これは(ポリモーフィック)関連付けをマッピングする通常の方法として意図されたものではないことは間違いありません。これは、非常に特殊な場合(監査ログ、ユーザーセッションデータなど)でのみ使用する必要があります。@Anyアノテーションは、メタデータ情報を保持する列を記述します。メタデータ情報の値と実際のエンティティタイプをリンクするには、@AnyDefおよび@AnyDefsアノテーションが使用されます。

@Any( metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )
@AnyMetaDef(
    idType = "integer",
    metaType = "string",
    metaValues = {
        @MetaValue( value = "S", targetEntity = StringProperty.class ),
        @MetaValue( value = "I", targetEntity = IntegerProperty.class )
} )
@JoinColumn( name = "property_id" )
public Property getMainProperty() {
    return mainProperty;
}

idTypeは、ターゲットエンティティの識別子プロパティタイプを表し、metaTypeはメタデータタイプ(通常は文字列)を表します。@AnyDefは相互化して再利用できることに注意してください。この場合、パッケージメタデータとして配置することをお勧めします。

//on a package
@AnyMetaDef( name="property"
idType = "integer",
metaType = "string",
metaValues = {
@MetaValue( value = "S", targetEntity = StringProperty.class ),
@MetaValue( value = "I", targetEntity = IntegerProperty.class )
} )
package org.hibernate.test.annotations.any;
//in a class
@Any( metaDef="property", metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER )
@JoinColumn( name = "property_id" )
public Property getMainProperty() {
    return mainProperty;
}

@ManyToAnyを使用すると、複数のテーブルからのクラスへのポリモーフィックな関連付けが可能になります。このタイプのマッピングには、常に複数の列が必要です。最初の列は、関連付けられたエンティティのタイプを保持します。残りの列は識別子を保持します。この種の関連付けに外部キー制約を指定することは不可能であるため、これは(ポリモーフィック)関連付けをマッピングする通常の方法として意図されたものではないことは間違いありません。これは、非常に特殊な場合(監査ログ、ユーザーセッションデータなど)でのみ使用する必要があります。

@ManyToAny(
metaColumn = @Column( name = "property_type" ) )
@AnyMetaDef(
    idType = "integer",
    metaType = "string",
    metaValues = {
@MetaValue( value = "S", targetEntity = StringProperty.class ),
@MetaValue( value = "I", targetEntity = IntegerProperty.class ) } )
@Cascade( { org.hibernate.annotations.CascadeType.ALL } )
@JoinTable( name = "obj_properties", joinColumns = @JoinColumn( name = "obj_id" ),
    inverseJoinColumns = @JoinColumn( name = "property_id" ) )
public List<Property> getGeneralProperties() {

Src:Hibernateアノテーションリファレンスガイド3.4.0GA

それが役に立てば幸い!

于 2008-10-20T09:26:34.153 に答える
4

@Any アノテーションは、複数のテーブルからのクラスへのポリモーフィックな関連付けを定義しますが、これらのようなポリモーフィックな関連付けは SQL アンチパターンです! 主な理由は、列が複数のテーブルを参照できる場合、FK 制約を定義できないことです。

Bill Karwin が著書で指摘した解決策の 1 つは、"type" を含む 1 つの列を使用する代わりに、unique 修飾子を使用して重複を回避する代わりに、"Any" の各型の交差テーブルを作成することです。このソリューションは、JPA で作業するのが面倒な場合があります。

Karwin によって提案された別の解決策は、接続された要素のスーパータイプを作成することです。本、DVD、または VHS を借りる場合を例にとると、スーパー タイプのアイテムを作成し、結合テーブルの戦略を使用して、アイテムから本、DVD、および VHS を継承させることができます。Borrow は Item を指します。このようにして、FKの問題を完全に回避できます。本の例を以下の JPA に翻訳しました。

@Entity
@Table(name = "BORROW")
public class Borrow{
//... id, ...
@ManyToOne Item item;
//...
}

@Entity
@Table(name = "ITEMS")
@Inheritance(strategy=JOINED)
public class Item{
  // id, ....
  // you can add a reverse OneToMany here to borrow.
}

@Entity
@Table(name = "BOOKS")    
public class Book extends Item {
  // book attributes
}

@Entity
@Table(name = "VHS")    
public class VHS extends Item {
  // VHSattributes
}

@Entity
@Table(name = "DVD")    
public class DVD extends Item {
  // DVD attributes
}
于 2015-10-06T14:45:35.420 に答える
2

@Any の Hibernate Annotations のドキュメントを読みましたか? 私自身はまだそれを使用していませんが、参照を定義する拡張された方法のようです。リンクには例が含まれていますが、概念を完全に理解するのに十分かどうかはわかりません...

于 2008-10-20T09:15:09.573 に答える