Możesz użyć tylko EntityGraph
jeśli atrybut asocjacji jest częścią nadklasy, a przez to również częścią wszystkich podklas. W przeciwnym razie EntityGraph
zawsze zakończy się niepowodzeniem z Exception
które obecnie otrzymujesz.
Najlepszym sposobem uniknięcia problemu wyboru N+1 jest podzielenie zapytania na 2 zapytania:
Pierwsze zapytanie pobiera MCValue
jednostki używające EntityGraph
aby pobrać asocjację zmapowaną przez selected
atrybut. Po tym zapytaniu te encje są następnie przechowywane w pamięci podręcznej pierwszego poziomu Hibernate / kontekście trwałości. Hibernate użyje ich podczas przetwarzania wyniku drugiego zapytania.
@Query("SELECT m FROM MCValue m") // add WHERE clause as needed ...
@EntityGraph(attributePaths = {"selected"})
public List<MCValue> findAll();
Drugie zapytanie pobiera następnie Answer
i używa EntityGraph
aby pobrać również powiązaną Value
podmioty. Dla każdej Value
Hibernate utworzy instancję określonej podklasy i sprawdzi, czy pamięć podręczna pierwszego poziomu zawiera już obiekt dla tej kombinacji klasy i klucza podstawowego. W takim przypadku Hibernate używa obiektu z pamięci podręcznej pierwszego poziomu zamiast danych zwróconych przez zapytanie.
@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();
Ponieważ pobraliśmy już wszystkie MCValue
encje z powiązanym selected
encje, teraz otrzymujemy Answer
encje z zainicjowaną value
stowarzyszenie. A jeśli powiązanie zawiera MCValue
podmiot, jego selected
powiązanie zostanie również zainicjowane.