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

Hibernate Java Discussion :

[hibernate, JPA]Fetch LAZY inefficace sur association bi-directionnelle


Sujet :

Hibernate Java

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2006
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 40
    Points : 18
    Points
    18
    Par défaut [hibernate, JPA]Fetch LAZY inefficace sur association bi-directionnelle
    Bonjour,

    Je travaille depuis 2 mois seulement avec hibernate et je rencontre un problème au niveau du rapatriement des données de collections liées à une entité. Je m'explique :

    J'ai deux entitées A et B liées par une association bi-directionnelle de type one-to-many (many-to-one) dont voici le code :

    Entity A :

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    @Entity
    @Table(name = "AS")
    //@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
    public class A {
     
     
    	private long id;
            private String property;
    	/**
             * collection of Bs.
             */
    	private Set<B> bs;
     
    	/**
             * Constructor.
             */
    	public A() {
    		bs = new HashSet<B>();
    	}
     
    	/**
             * Gets the id.
             * 
             * @return id
             */
    	@Id
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	@Column(name = "ID")
    	public long getId() {
    		return id;
    	}
     
    	/**
             * Sets the id.
             * 
             * @param id
             *            candidate id
             */
    	public void setId(long id) {
    		this.id = id;
    	}
     
            @Column(name = "property")
            public String getProperty() {
                    return property;
            }
     
            public void setProperty(String property) {
                    this.property = property;
            }
     
    	/**
             * Gets the B set.
             * 
             * @return B set
             */
    	@OneToMany(mappedBy = "a", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    	public Set<B> getBs() {
    		return this.bs;
    	}
     
    	/**
             * Sets the B set.
             * 
             * @param bs
             */
    	public void setBs(final Set<B> bs) {
    		for (B b : bs) {
    			b.setA(this);			
    		}
    		this.bs = bs;
    	}
     
    }
    Entity B :

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    @Entity
    @Table(name = "BS")
    public class Context {
     
    	/**
             * Id.
             */
    	private long id;
    	/**
             * A.
             */
    	private A a;
     
    	/**
             * Default Constructor.
             */
    	Context() {
    	}
     
    	/**
             * Gets the id.
             * 
             * @return id
             */
    	@Id
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	@Column(name = "ID")
    	public long getId() {
    		return id;
    	}
     
    	/**
             * Sets the id.
             * 
             * @param id
             *           
             */
    	public void setId(long id) {
    		this.id = id;
    	}
     
    	/**
             * Gets a.
             * 
             * @return a
             */
    	@ManyToOne(fetch=FetchType.LAZY)
    	@JoinColumn(name = "FKAId", nullable = false)
    	public A getA() {
    		return a;
    	}
     
    	/**
             * Sets a.
             * 
             * @param a
             */
    	public void setA(A a) {
    		this.a = a;
    	}
     
    }
    L'idée c'est que je ne veux pas remplir le set de B dans A à chaque fois que je fais une requête sur A comme ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A a = adao.findById(1L, false);
    		assertNotNull(a);
    		assertEquals("property1", a.getProperty());
    Seulement, lorsque je fais cela, les logs m'indiquent que deux requêtes sont lancées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Hibernate: select A0_.ID as A1_8_0_, candidate0_.property as property8_0_ from AS A0_ where A0_.ID=?
    Hibernate: select B0_.FKAId as FKA5_1_, B0_.ID as BID1_, B0_.ID as BID10_0_, B0_.FKAId as FKA5_10_0_ from BS B0_ where B0_.FKAId=?
    ou le ? = 1L

    Moi ce que je voudrais, c'est qu'il ne fasse le deuxième select que si je le demande (que je fais explicitement un A.getBs()). Je pensais que cela pouvait être grâce aux fetch = FetchType.LAZY placés au niveau des @oneToMany (il semble d'ailleurs que ceux placés dans les @manyToOne fonctionnent eux...)

    Il y aurait-il quelque chose que j'aurais loupé ??

    en attendant une réponse de votre part, bonne journée !

  2. #2
    Membre à l'essai
    Inscrit en
    Juin 2006
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 40
    Points : 18
    Points
    18
    Par défaut
    Bon et bien sans avoir eu de réponses, j'ai fini par trouver où était le problème donc je vais le poster pour si des fois certaines personnes finissaient par avoir le même problème...

    il se situe ici en rouge :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	/**
    	 * Sets the B set.
    	 * 
    	 * @param bs
    	 */
    	public void setBs(final Set<B> bs) {
    		for (B b : bs) {
    			b.setA(this);			
    		}
    		this.bs = bs;
    	}
    En fait, lorsque j'avais créé mon appli, j'avais besoin à un moment de spécifier à l'objet fils quel était son père (afin de remplir le champ de clé étrangère) sinon, je me retrouvait avec une erreur SQl due au fait que la colonne de clé étrangère n'était pas nullable (normal).

    Le souci, c'est qu'ensuite, lorsqu'hibernate (ou le jpa) rapatriait les données dans les entités, il passait par le setBs() et donc faisait un select sur tous les Bs pour appeler le setA() ( does it make sense ??) ce que je ne voulais pas bien entendu !

    Il faut donc prévoir un autre setter pour lier les entités au moment de la création différent du setter de base ou alors faire un addB(B b) dans lequel on lie les données...comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    	public void setBs(final List<B> bs) {
    		this.bs = bs;
    	}
     
     
    	public final void addB(final B b) {
    		query.setA(this); //on lie les données à ce moment là
    		this.bs.add(b);
    	}
    Voilà, c'était un peu sioux comme concept et plutôt fastidieux à débugger mais maintenant ça fonctionne comme je le veux ! YiiiiiiiHaaaaaa

    merci quand même...

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 30/10/2012, 09h04
  2. Hibernate / JPA et infos stockées dans la table association
    Par nassarane dans le forum Hibernate
    Réponses: 1
    Dernier message: 22/11/2011, 14h54
  3. Réponses: 0
    Dernier message: 19/04/2009, 20h50
  4. Probleme Hibernate + JPA -> lazy loading non respecté
    Par MikoMax dans le forum Hibernate
    Réponses: 1
    Dernier message: 28/08/2007, 15h13
  5. Lazy loading sur component
    Par El Saigneur dans le forum Hibernate
    Réponses: 2
    Dernier message: 03/11/2006, 10h30

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