IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Spring Java Discussion :

Recherche explication et solution pour performance JPA [Data]


Sujet :

Spring Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2005
    Messages
    489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2005
    Messages : 489
    Par défaut 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    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 SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Salut.
    Quand tu fais ta requête sur ReferentielMetal, JPA va charger l'objet Referentiel car les relations ManyToOne sont chargées automatiquement par défaut.
    https://vladmihalcea.com/hibernate-f...etch-strategy/

    Si tu modifies ton annotation de la sorte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    @ManyToOne(fetch = FetchType.LAZY)
    la requête problématique ne devrait plus s'exécuter.

  3. #3
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2005
    Messages
    489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2005
    Messages : 489
    Par défaut
    Je l'avais tenté, mais ça ne change strictement rien.. le comportement est le même..

  4. #4
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 963
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 963
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    from referentiel_digital
    c’est une autre entité qui est fetchée, qu’on ne voit pas dans le code montré

  5. #5
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2005
    Messages
    489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2005
    Messages : 489
    Par défaut
    Bien vu...
    J'avoue sur le coup, j'ai été nul..

    l'entité en question

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    @Entity
    @Table(name = "referentiel_digital")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public class ReferentielDigital implements Serializable {
     
        private static final long serialVersionUID = 1L;
     
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
     
        @NotNull
        @Size(max = 200)
        @Column(name = "libelle_commercial", length = 200, nullable = false)
        private String libelleCommercial;
     
        @Size(max = 1000)
        @Column(name = "description_courte", length = 1000)
        private String descriptionCourte;
     
        @Column(name = "description_longue", columnDefinition="clob")
        private String descriptionLongue;
     
        @NotNull
        @Column(name = "date_creation", nullable = false)
        private ZonedDateTime dateCreation;
     
        @Column(name = "date_modification")
        private ZonedDateTime dateModification;
     
        @OneToOne(fetch = FetchType.LAZY)
        @JoinColumn(unique = true)
        private Referentiel reference;
    j'ai ajouté à l'instant le "(fetch = FetchType.LAZY)" et ça semble mieux

    A confirmer. Si c'est ok, je passerai en résolu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 26/12/2018, 17h08
  2. Réponses: 0
    Dernier message: 24/11/2015, 19h44
  3. [JUnit] [EJB] Recherche une vraie solution pour tester des EJB 3+
    Par Khaled.Noordin dans le forum Tests et Performance
    Réponses: 1
    Dernier message: 23/01/2012, 15h17
  4. Réponses: 4
    Dernier message: 25/05/2010, 14h59
  5. Recherche d'une solution pour créer un robot
    Par FabaCoeur dans le forum C++
    Réponses: 10
    Dernier message: 16/09/2009, 19h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo