7

次のような多対多の関係を持つ JPA オブジェクトがあります。

@Entity
public class Role {
    //...

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
    name="RolePrivilege",
    joinColumns=
        @JoinColumn(name="role", referencedColumnName="ID"),
    inverseJoinColumns=
        @JoinColumn(name="privilege", referencedColumnName="ID")
    )
    private Set<Privilege> privs;
}

RolePrivilege の JPA オブジェクトがないため、ロール オブジェクトの privs フィールドからエントリを削除する JPQL クエリの記述方法がわかりません。たとえば、私はこれを試しましたが、うまくいきません。Role.privs がマップされていないと文句を言います。

DELETE FROM Role.privs p WHERE p.id=:privId

他に何を試すべきかわかりません。もちろん、結合テーブル RolePrivilege から削除するネイティブ クエリを作成することもできます。しかし、そうすることで、ネイティブ クエリによって更新されないローカルにキャッシュされたオブジェクトとのやり取りがうまくいかないのではないかと心配しています。

このような結合テーブルからエントリを削除するためにJPQLを書くことさえ可能ですか? そうでない場合は、すべての Role オブジェクトをロードし、それぞれの privs コレクションからエントリを削除してから、各ロールを永続化できます。しかし、単純な JPQL クエリですべてを一度に実行できるのであれば、それを行うのはばかげているように思えます。

4

3 に答える 3

3

JPQL の update および delete ステートメントは、テーブル名ではなくエンティティ名を参照する必要があるため、提案したアプローチでは運が悪いと思います。

JPA プロバイダーによっては、単純な生の SQL ステートメント (100% 移植可能である必要があります) を使用して JoinTable からエントリを削除し、キャッシュ プロバイダー API をプログラムで操作してデータを削除することができます。たとえば、Hibernate では、evict() を呼び出して、第 2 レベルのキャッシュからすべての「Role.privs」コレクションを期限切れにすることができます。

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs
sessionFactory.evictCollection("Role.privs"); //evict all privs collections

残念ながら、私は正確に何がサポートされているかを知るのに十分な JPA API を扱っていません。

于 2009-07-02T06:04:56.667 に答える
3

また、多対多の関係 (結合テーブルに含まれる) を削除する JPQL アプローチも探していました。明らかに、ORM にはテーブルの概念がないため、DELETE 操作を使用することはできません... しかし、これらの場合のための特別な演算子があればいいのにと思います。リンクとリンク解除のようなもの。もしかしたら今後の機能?

とにかく、この必要性を達成するために私が行ってきたことは、多対多の関係をマップするエンティティ Bean に実装されたコレクションを操作することでした。

たとえば、コースと多対多の関係を持つクラス Student を取得した場合:

@ManyToMany
private Collection <Courses> collCourses;

そのコレクションのゲッターとセッターをエンティティに組み込みます。次に、たとえば EJB から getter を使用してコレクションを取得し、目的の Course を追加または削除し、最後に setter を使用して新しいコレクションを割り当てます。そして、それは完了です。それは完全に機能します。

しかし、私の主な懸念はパフォーマンスです。ORM は、すべてのオブジェクトの巨大なキャッシュを保持することになっています (私の間違いでなければ) が、それを使用してより高速に動作する場合でも、コレクションからすべての要素を取得することが本当に効果的かどうか疑問に思います...

私にとっては、テーブルからレジストリを取得し、内部 DB エンジン (SQL、JPQL など) と直接的または間接的に動作するクエリ言語の代わりに、純粋な Java を使用してそれらをポストフィルター処理するのと同じくらい非効率的だからです。

于 2009-07-19T14:50:03.457 に答える
2

Java はオブジェクト指向言語であり、ORM の要点は結合テーブルなどの詳細をユーザーから隠すことです。したがって、結果を考慮せずに結合テーブルからの削除を検討することさえ奇妙になります。

いいえ、エンティティ用のJPQLではできません。

いずれかの端でエンティティを取得し、それらのコレクションをクリアします。これにより、結合テーブルのエントリが削除されます。オブジェクト指向。

于 2009-07-03T07:52:41.300 に答える