2017-09-26 6 views
0

J'ai une relation OneToOne dans mon modèle de données, et Hibernate interroge TOUJOURS les deux entités afin de générer le jeu de résultats.Hibernate exécutant toujours la requête redondante

C'est le modèle de données

@Entity 
public class C1 { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, targetEntity = C2.class) 
    private C2 c2; 

    //... other stuff 
} 


@Entity 
public class C2 extends OtherClassOutOfDomain { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "c2") 
    private C1 c1; 

    //... other stuff 
} 

Hibernate générer mon schéma que deux tables et la table C1 a une clé étrangère à C2, ce qui me est parfait comme je vais utiliser plus souvent le C1.

MAIS

Chaque fois que je requête pour C1 générer hibernation une requête joignant les deux données entités par ligne, et de générer des requêtes N pour chaque ligne dans le résultat de la première (avant même accéder à l'ensemble de résultats)

exemple

Hibernate (just one): 
    select 
     this_.id as id1_2_1_, 
     this_.c2_id as authDat22_2_1_, 
     this_.bio as bio2_2_1_, 
     this_.blocked as blocked3_2_1_, 
     this_.commentsAmount as comments4_2_1_, 
     this_.confirmed as confirme5_2_1_, 
     this_.deleted as deleted6_2_1_, 
     c22_.id as id1_0_0_, 
     c22_.adid as adid2_0_0_, 
    from 
     c1 this_ 
    inner join 
     c2 c22_ 
      on this_.authData_id=c22_.id 

Hibernate (N times as the size of previous query): 
    select 
     this_.id as id1_2_1_, 
     this_.c2_id as authDat22_2_1_, 
     this_.bio as bio2_2_1_, 
     this_.blocked as blocked3_2_1_, 
     this_.commentsAmount as comments4_2_1_, 
     this_.confirmed as confirme5_2_1_, 
     this_.deleted as deleted6_2_1_, 
     c22_.id as id1_0_0_, 
     c22_.adid as adid2_0_0_, 
    from 
     c1 this_ 
    inner join 
     c2 c22_ 
      on this_.authData_id=c22_.id 
    where 
      this_.authData_id=? 
.....repeat 
.....repeat 
.....repeat 

le résultat des requêtes répétées est cointained dans la ligne de la première grande question ... est-il possible d'éviter ces demandes unecessary? i essayé Définir comme paresseux, mais il travaille didnt

le code que je suis en cours d'exécution pour obtenir ce comportement est simple

HibernateUtils.createNewSession().createCriteria(C1.class).list(); 

Je ne suis même pas accès au résultat avant qu'il déclenche les requêtes imbriquées

J'utilise hibernate 5.10 e mysql 5.7.17

+0

option = false? S'il vous plaît essayez avec vrai –

Répondre

0

J'ai obtenu une solution mais je n'ai pas complètement compris pourquoi.

Comme cartographie relation OneToOne avec JPA mise en veille prolongée va mettre la clé étrangère sur l'entité qui a l'attribut « targetEntity » (L'ENTITÉ AVEC LE ATTRIBUT L'ENTITÉ setted EN atribute VALEUR)

Alors que l'interrogation par une entité a une clé étrangère dans sa mise en veille prolongée de la structure interrogera automatiquement les entités imbriquées (je ne sais pas la raison)

pour résoudre mon précédent problème lié, je avais juste besoin de changer l'annotation à

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, mappedBy= "c1") 
private C2 c2; 

@OneToOne(fetch = FetchType.LAZY, targetEntity = C1.class) 
private C1 c1; 
0

Gardez ces deux choses dans votre esprit.

La stratégie de récupération par défaut de OneToOne est EAGER.

LAZY peut uniquement fonctionner sur une association OneToOne si l'association est non nullable.

Votre problème est similaire à N + 1 Sélectionne problème

Resolve N + 1 selects problème:

HQL chercher rejoindre

Soit

de C1 c1 jointure gauche Allez chercher c1.c2

ou

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, mappedBy= "c1") 
@Fetch(FetchMode.JOIN) 
private C2 c2; 

et deuxième classe

@OneToOne(fetch = FetchType.LAZY, mappedBy = "c2") 
@Fetch(FetchMode.JOIN) 
private C1 c1;