Recherche explication et solution pour performance JPA
Bonjour,
J'espère déjà posté au bon endroit. Voilà, je suis sur un projet généré avec JHIPSTER. Tout fonctionne parfaitement, je suis très content de la techno. Je suis passé sur le côté "performance" du projet.
Aujourd'hui, j'ai une API qui prend du temps, et j'ai trouvé (je pense) la raison.
Je vais essayer d'être clair, sans mettre trop d'informations pour vous noyer.
Je dispose d'un objet central "Referentiel", qui contient beaucoup d'objets avec la relation @OneToMany. j'ai volontairement déclarés certaines de ces relations car j'utilise Criteria pour mon APIs de recherche.
Exemple de mon objet :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| @Entity
@Table(name = "referentiel")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Referentiel implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Column(name = "uuid", nullable = false)
private UUID uuid;
...
@ManyToMany
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JoinTable(name = "referentiel_catalogue",
joinColumns = @JoinColumn(name = "referentiel_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "catalogue_id", referencedColumnName = "id"))
private Set<RefCatalogueEntite> catalogues = new HashSet<>();
@OneToMany(mappedBy = "reference")
@JsonIgnoreProperties("referentiels")
private Set<ReferentielAttribut> attributs = new HashSet<>();
@OneToMany(mappedBy = "reference")
@JsonIgnoreProperties("referentiels")
private Set<ReferentielMetal> metaux = new HashSet<>();
@OneToOne(mappedBy = "reference")
@JsonIgnoreProperties("referentiels")
private ReferentielDigital digital; |
Ma requête avec CRITERIA me retourne ma liste de références, et pour compléter mes données de sortie, pour chaque Referentiel lu, je vais lire en base les données liés aux relations de type @OneToMany, et donc par exemple ReferentielMetal.
Requête effectué dans "ReferentielMetalRepository"
Code:
1 2
| @Query("select referentiel_metal from ReferentielMetal referentiel_metal where referentiel_metal.reference.id = :referenceId")
List<ReferentielMetal> findAllByReferenceId(@Param("referenceId") Long referenceId); |
Extrait de la classe "ReferentielMetal " :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Entity
@Table(name = "referentiel_metal")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ReferentielMetal implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "principal")
private Boolean principal;
...
@ManyToOne
@JsonIgnoreProperties("referentielMetals")
private Referentiel reference;
@ManyToOne
@JsonIgnoreProperties("referentielMetals")
private Metal metal; |
Ce que je ne comprends pas, c'est que lors de l'exécution de cette requête, dans mes logs je vois bien son appel :
Code:
select referentie0_.id as id1_89_, referentie0_.createur_id as createur6_89_, referentie0_.date_creation as date_cre2_89_, referentie0_.date_modification as date_mod3_89_, referentie0_.metal_id as metal_id7_89_, referentie0_.modificateur_id as modifica8_89_, referentie0_.poids as poids4_89_, referentie0_.principal as principa5_89_, referentie0_.reference_id as referenc9_89_ from referentiel_metal referentie0_ where referentie0_.reference_id=?
Par contre, une requête est aussi faite sur l'entité Referentiel (celle justement qui me pose problème de performance, mais aussi sur l'entité Metal :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| select referentie0_.id as id1_89_, referentie0_.createur_id as createur6_89_, referentie0_.date_creation as date_cre2_89_, referentie0_.date_modification as date_mod3_89_, referentie0_.metal_id as metal_id7_89_, referentie0_.modificateur_ ...
from referentiel_digital referentie0_
left outer join jhi_user user1_ on referentie0_.createur_id=user1_.id
left outer join jhi_user user2_ on referentie0_.modificateur_id=user2_.id
left outer join referentiel referentie3_ on referentie0_.reference_id=referentie3_.id
left outer join fournisseur_entite fournisseu4_ on referentie3_.code_fournisseur_id=fournisseu4_.id
left outer join jhi_user user5_ on fournisseu4_.createur_id=user5_.id
left outer join entite entite6_ on fournisseu4_.entite_id=entite6_.id
left outer join jhi_user user7_ on entite6_.createur_id=user7_.id
left outer join entite entite8_ on entite6_.entite_mere_id=entite8_.id
left outer join jhi_user user9_ on entite8_.modificateur_id=user9_.id
left outer join type_entity typeentity10_ on entite8_.type_entity_id=typeentity10_.id
left outer join jhi_user user11_ on fournisseu4_.modificateur_id=user11_.id
left outer join fournisseur fournisseu12_ on fournisseu4_.referentiel_id=fournisseu12_.id
left outer join jhi_user user13_ on fournisseu12_.createur_id=user13_.id
left outer join four_edi_format_fichier fouredifor14_ on fournisseu12_.edi_format_fichier_id=fouredifor14_.id
left outer join jhi_user user15_ on fouredifor14_.createur_id=user15_.id
left outer join jhi_user user16_ on fouredifor14_.modificateur_id=user16_.id
left outer join entite entite17_ on fournisseu12_.fabricant_id=entite17_.id
left outer join four_methode_acces_photo fourmethod18_ on fournisseu12_.methode_acces_photo_id=fourmethod18_.id
left outer join jhi_user user19_ on fourmethod18_.createur_id=user19_.id
left outer join jhi_user user20_ on fourmethod18_.modificateur_id=user20_.id
left outer join jhi_user user21_ on fournisseu12_.modificateur_id=user21_.id
left outer join pays pays22_ on fournisseu12_.pays_id=pays22_.id
left outer join jhi_user user23_ on referentie3_.createur_id=user23_.id
left outer join entite entite24_ on referentie3_.entite_id=entite24_.id
left outer join jhi_user user25_ on referentie3_.modificateur_id=user25_.id
left outer join referentiel referentie26_ on referentie3_.reference_mere_id=referentie26_.id
left outer join tva tva27_ on referentie26_.taxe1_id=tva27_.id
left outer join tva tva28_ on referentie26_.taxe2_id=tva28_.id
where referentie0_.reference_id=? |
Je ne comprends pas pourquoi cette requête est effectuée, je n'en ai pas besoin, et elle prend trop de temps (pas étonnant vu le nombre de jointures gauches).
Auriez-vous une explication ? et aussi une solution svp?
D'avance merci