Étant donné le modèle de domaine suivant, je veux charger tous les Answer
, y compris leurs Value
et leurs sous-enfants respectifs, et les placer dans un AnswerDTO
pour ensuite les convertir en JSON. J'ai une solution fonctionnelle mais elle souffre du problème N + 1 dont je veux me débarrasser en utilisant un @EntityGraph
. Toutes les associations sont configurées LAZY
.
@Query("SELECT a FROM Answer a")
@EntityGraph(attributePaths = {"value"})
public List<Answer> findAll();
Utilisation d'un @EntityGraph
sur la méthode Repository
Je peux m'assurer que les valeurs sont pré-extraites pour empêcher N + 1 sur le Answer->Value
association. Bien que mon résultat soit correct, il y a un autre problème N + 1, à cause du chargement paresseux de l'association selected
des MCValue
s.
Utiliser ceci
@EntityGraph(attributePaths = {"value.selected"})
échoue, car le champ selected
n'est bien sûr qu'une partie de certaines des entités Value
:
Unable to locate Attribute with the the given name [selected] on this ManagedType [x.model.Value];
Comment puis-je dire à JPA d'essayer de récupérer uniquement l'association selected
au cas où la valeur serait un MCValue
? J'ai besoin de quelque chose comme optionalAttributePaths
.
Modifié après votre commentaire:
Je m'excuse, je n'ai pas compris votre problème au premier tour, votre problème se produit au démarrage de spring-data, pas seulement lorsque vous essayez d'appeler findAll ().
Ainsi, vous pouvez maintenant naviguer dans l'exemple complet qui peut être extrait de mon github: https://github.com/bdzzaid/stackoverflow-Java/blob/master/jpa-hibernate/
Vous pouvez facilement reproduire et résoudre votre problème dans ce projet.
En effet, les données Spring et la mise en veille prolongée ne sont pas capables de déterminer le graphique "sélectionné" par défaut et vous devez spécifier la manière de collecter l'option sélectionnée.
Donc d'abord, vous devez déclarer les NamedEntityGraphs de la classe Answer
Comme vous pouvez le voir, il y a deux NamedEntityGraph pour l'attribut value de la classe Réponse
Le premier pour tous Valeur sans relation spécifique à charger
Le second pour la valeur spécifique Multichoice . Si vous supprimez celui-ci, vous reproduisez l'exception.
Deuxièmement, vous devez être dans un contexte transactionnel answerRepository.findAll () si vous souhaitez récupérer des données de type [~ # ~] paresseux [~ # ~]
@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;
// ..
}