次のドメインモデルを前提として、Answer
sとそれぞれのサブ子を含むすべてのValue
sを読み込み、それをAnswerDTO
に入れてJSONに変換します。有効な解決策はありますが、アドホック@EntityGraph
を使用して解消したいN + 1の問題があります。すべての関連付けは_LAZY
で構成されます。
@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();
Repository
メソッドでアドホック@EntityGraph
を使用すると、Answer->Value
アソシエーションでN + 1が発生しないように値をプリフェッチできます。私の結果は問題ありませんが、selected
sのMCValue
関連付けを遅延ロードするため、別のN + 1問題があります。
これを使う
@EntityGraph(attributePaths = {"value.selected"})
selected
フィールドは、もちろん一部のValue
エンティティの一部にすぎないため、失敗します。
Unable to locate Attribute with the the given name [selected] on this ManagedType [x.model.Value];
値がselected
の場合に、JPAがMCValue
関連付けのみをフェッチしようとするようにするにはどうすればよいですか? optionalAttributePaths
のようなものが必要です。
コメントの後に編集:
申し訳ありませんが、最初のラウンドでは問題を理解していません。問題は、findAll()を呼び出そうとしたときだけでなく、spring-dataの起動時に発生します。
ですから、完全な例をナビゲートして、私のgithubからプルすることができます: https://github.com/bdzzaid/stackoverflow-Java/blob/master/jpa-hibernate/
このプロジェクト内で問題を簡単に再現して修正できます。
事実上、Springデータと休止状態は、デフォルトでは「選択された」グラフを決定することができず、選択されたオプションを収集する方法を指定する必要があります。
したがって、最初に、クラスのNamedEntityGraphsを宣言する必要がありますAnswer
ご覧のとおり、クラスの属性valueには2つのNamedEntityGraphがありますAnswer
最初のすべてValue負荷との特定の関係なし
特定のMultichoice値の2番目。これを削除すると、例外が再現されます。
2番目に、トランザクションコンテキストである必要がありますanswerRepository.findAll()タイプのデータをフェッチする場合[〜#〜] lazy [〜#〜]
@Entity
@Table(name = "answer")
@NamedEntityGraphs({
@NamedEntityGraph(
name = "graph.Answer",
attributeNodes = @NamedAttributeNode(value = "value")
),
@NamedEntityGraph(
name = "graph.AnswerMultichoice",
attributeNodes = @NamedAttributeNode(value = "value"),
subgraphs = {
@NamedSubgraph(
name = "graph.AnswerMultichoice.selected",
attributeNodes = {
@NamedAttributeNode("selected")
}
)
}
)
}
)
public class Answer
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(updatable = false, nullable = false)
private int id;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "value_id", referencedColumnName = "id")
private Value value;
// ..
}