web-dev-qa-db-ja.com

@OneToMany関連付けの結果をフィルタリングするアノテーション

2つのテーブル間に親子関係があり、対応するマッピングがmy Javaクラスにあります。テーブルはおおよそ次のようになります。

A (ref number, stuff varchar2(4000))
B (a_ref number, other number, foo varchar2(200))

およびJavaコード:

@Entity
class A {
    @Id
    @Column(name = "REF")
    private int ref;

    @OneToMany
    @JoinColumn(name = "A_REF", referencedName = "REF")
    private Set<B> bs;
}

@Entity
class B {
    @Id
    @Column(name = "A_REF")
    private int aRef;

    @Id
    @Column(name = "OTHER")
    private int other;
}

これは正常に機能しますが、子テーブルから取得する行にフィルターを追加したいと思います。生成されるクエリは次のようになります。

select a_ref, other, foo from B where a_ref = ?

そして私はそれが欲しいです:

select a_ref, other, foo from B where a_ref = ? and other = 123

追加のフィルターは、列名とハードコードされた値のみです。休止状態の注釈を使用してそれを行う方法はありますか?

私は@JoinFormulaを見てきましたが、それでは常に(JoinFormulaのname属性で)親テーブルの列名を参照する必要があります。

アドバイスを事前にありがとう。

22
Xavier

JPAではサポートされていませんが、JPAプロバイダーとしてhibernateを使用している場合は、アノテーション@FilterDefおよび@Filterを使用できます。

Hibernate Coreリファレンスドキュメント

Hibernate3には、フィルター基準を事前に定義し、それらのフィルターをクラスレベルとコレクションレベルの両方でアタッチする機能があります。フィルター基準を使用すると、クラスおよびさまざまなコレクション要素で使用可能な既存の「where」属性と同様の制限句を定義できます。ただし、これらのフィルター条件はパラメーター化できます。その後、アプリケーションは、特定のフィルターを有効にするかどうか、およびそれらのパラメーター値を実行時に決定することができます。フィルターはデータベースビューのように使用できますが、アプリケーション内でパラメーター化されます。

@Entity
public class A implements Serializable{
    @Id
    @Column(name = "REF")
    private int ref;

    @OneToMany
    @JoinColumn(name = "A_REF", referencedColumnName = "REF")   
    @Filter(name="test")
    private Set<B> bs;
}

@Entity
@FilterDef(name="test", defaultCondition="other = 123")
public class B implements Serializable{
    @Id
    @Column(name = "A_REF")
    private int aRef;

    @Id
    @Column(name = "OTHER")
    private int other;
}

Session session = entityManager.unwrap(Session.class);
session.enableFilter("test");
A a = entityManager.find(A.class, new Integer(0))
a.getb().size() //Only contains b that are equals to 123
29
Joel Hudon

jPA 1では、提供されたソリューションを使用できますが、unwrapをgetDelegateに変更して、

Session session = (Session)entityManager.getDelegate();

そしてそれはうまくいくでしょう。

2
MSaudi

別の解決策は、Hibernateの@Whereを使用することです: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#pc-where

    @OneToMany
    @JoinColumn(name = "A_REF", referencedName = "REF")
    @Where(clause = "other = 123")
    private Set<B> bs;
0
Uri Loya

私が質問を正しく理解している場合、javax.persistenceアノテーションを使用してこれを行う方法があります(私はこれをManyToOneで自分で使用し、 here からの回答を調整しました)。

@JoinColumns({
    @JoinColumn(name = "A_REF", referencedColumnName = "REF"),
    @JoinColumn(name = "B_TABLE_NAME.OTHER", referencedColumnName = "'123'")})
@OneToMany
private Set<B> bs;

ReferencesColumnNameのsingle引用符に注意してください。これは探している値です。

詳細 ここ

0
Hans Wouters