web-dev-qa-db-ja.com

初期化なしのHibernateカウントコレクションサイズ

初期化せずに関連するコレクションのサイズを数える方法はありますか?

例えば.

Select count(p.children) from Parent p

(私のwhere句がより複雑であり、私のfrom句がポリモーフィッククエリであるため、他の方法でこれを実行できないのには十分な理由があります)

ありがとう。

37
DD.

クエリ以外の可能な解決策は、childrenを_lazy="extra"_(XML表記)でマッピングすることです。このように、必要なクエリでParentをフェッチし、コレクション全体をロードせずにparent.getChildren().size()を呼び出すことができます(_SELECT COUNT_タイプのクエリのみが実行されます)。

注釈があれば、

_@OneToMany
@org.hibernate.annotations.LazyCollection(
org.hibernate.annotations.LazyCollectionOption.EXTRA
)
private Set<Child> children = new HashSet<Child>();
_

更新:Java Persistence with Hibernate 、ch。 13.1.3:

識別子ゲッターメソッドではないメソッドを呼び出すとプロキシが初期化され、要素の反復を開始するか、size()などのコレクション管理操作を呼び出すと、コレクションが初期化されます。 contains()。 Hibernateは、大規模なコレクションで主に役立つ追加の設定を提供します。それらはextra lazyとしてマップできます。 [...]

[上記のようにマップされます] size()contains()、またはisEmpty()を呼び出しても、コレクションは初期化されなくなります—必要な情報を取得するためにデータベースがクエリされます。 MapまたはListの場合、操作containsKey()およびget()もデータベースに直接クエリします。

したがって、上記のようにマッピングされたエンティティを使用すると、次のことができます

_Parent p = // execute query to load desired parent
// due to lazy loading, at this point p.children is a proxy object
int count = p.getChildren().size(); // the collection is not loaded, only its size
_
60
Péter Török

コレクションを明示的に操作するHQLの形式であるSession#createFilterを使用できます。たとえば、ParentとChildrenについて言及しているので、Person pがある場合、最も基本的な形式は次のようになります。

session.createFilter( p.getChildren(), "" ).list()

これは単に子のリストを返すだけです。返されるコレクションは「ライブ」ではなく、pに関連付けられていないことに注意してください。

興味深い部分は、2番目の引数にあります。これはHQLフラグメントです。ここでは、例えば、あなたが望むかもしれません:

session.createFilter( p.getChildren(), "select count(*)" ).uniqueResult();

あなたはwhere句を持っていると述べたので、あなたはまた望むかもしれません:

session.createFilter( p.getChildren(), "select count(*) where this.age > 18" ).uniqueResult();

From句がないことに注意してください。つまり、from句は協会から暗示されています。コレクションの要素にはエイリアス「this」が与えられているため、HQLフラグメントの他の部分から参照できます。

1
Steve Ebersole