2016-07-07 19 views
1

SpringデータJPA(現在4.0.8)とHibernate(現在4.2.16)を使用しているため、JPA OneToManyリストの副選択ヒットへのページネゴシエーションに問題があります。内部リストでは、副選択は、指定されたページの主要素だけでなく、主要素と結合するすべての要素を選択します。Spring Data JPA OneToManyページングFetchType subselect

例えば:

主JPAエンティティ:JPAエンティティのプライマリリストを取得するために生成される

@Entity 
@NamedQuery(name="Message.findAll", query="SELECT m FROM Message m") 
public class Message implements Serializable { 
... 
//uni-directional many-to-one association to Message_Review 
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER) 
@JoinColumn(name="message_id", referencedColumnName="message_id", insertable=false, updatable=false) 
@Fetch(FetchMode.SUBSELECT) 
private Set<Message_Review> messageReviews; 

SQLのようなある:のベースリスト後

SELECT TOP ? MESSAGE0_.MESSAGE_ID AS MESSAGE_1_0_, MESSAGE0_....... AND NOT (EXISTS (SELECT MESSAGEREV1_.MESSAGE_ID, MESSAGEREV1_.......)) 

JPAエンティティ、Spring Data JPA(またはHibernate)は、(@ FetchMode.SUBSELECTごとに)OneToManyリストを照会します。

SELECT messagerev0_.message_id as message_2_0_1_, 
..... 
where messagetop0_.message_id in 
(select message0_.message_id 
from ....... 
) 

OneToManyヒットのインナーセレクトには、TOPが関連付けられていないことに注意してください。したがって、メッセージレビューのすべてを元に戻しています(JPAがそれにマッチさせる必要があるものだけではなく)。通常、これは大きな問題ではありませんが、OneToManyリストに実質的に大きなデータセットがある場合、ペイロードは、特定のページに対して非常に小さなサブセットしか必要としない場合、データベースから数百万のアイテムを戻す可能性があります。

@ FetchMode.SubSelectを利用してSQLヒット数を制限すると、ページングをOneToManyに引き継ぐ方法についてのアイデアはJPAエンティティでリストされていますか?

答えて

0

こんにちは、これはSubselectのフェッチがある場合、非常に正常な動作です。これはそうなるはずです。よりスクロール可能な振る舞いが必要な場合は、@ BatchSize(size = 5)アノテーションを使用できます。ここでは、一度に取り出されるコレクションの数がわかります。

ですから、カテゴリーのようなもの持って言うことができます - >項目の関係を、あなたが実行します。

は、あなたがカテゴリを反復開始カテゴリー

から*を選択します。 アイテムにアクセスすると、関連する5つのコレクションが返されます。あなたを介してナビゲートしているカテゴリが、次の5

のクエリモミ項目は次のようになりますだけでなく、:

(1,2,3,4,5)で項目カテゴリIDから選択*

あなたが必要とするものは、@ BatchSizeとFetchType.Selectの組み合わせです。

私は説明があまりよくありませんので、リンクも送っています。 Subselectは非常に早期に使用されることに注意してください。 http://www.mkyong.com/hibernate/hibernate-fetching-strategies-examples/

長所とサブセレクト対のBatchSizeの短所:

大きなバッチサイズより大きなメモリ消費量は、必要以上のCPU。私は、バッチサイズを低く保つことは、限られたリソースを持つデバイスに適していると思います。 Hibernateチュートリアルを開くと、@ BatchSizeがパフォーマンスチューニングの章で説明されていることがわかります。 Subselect戦略と同じですが、サブセレクトは大きなデータセットに対して非常に重いことがあります。この点に関して、BatchSizeを使用することは、N + 1選択問題と同時にメモリ消費量を低く抑えるという点で優れた妥協点です。

+0

私はこれが私が行方不明であると信じています。エンティティのBatchSizeを設定することの欠点は何ですか? (あなたがEAGERの初期化を使用している場合は、それが理由で「1」にデフォルト設定されていると仮定します)? – LetsBeFrank

+1

バッチサイズが大きければ大きいほど、メモリ消費量は大きくなります。必要なCPUが増えます。私は、バッチサイズを低く保つことは、限られたリソースを持つデバイスに適していると思います。 Hibernateチュートリアルを開くと、@ BatchSizeがパフォーマンスチューニングの章で説明されていることがわかります。 Subselect戦略と同じですが、サブセレクトは大きなデータセットに対して非常に重いことがあります。この点に関して、BatchSizeを使用することは、N + 1選択問題と同時にメモリ消費量を低く抑えるという点で優れた妥協点です。 –

関連する問題