Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    May 2010
    Messaggi
    457

    Property Eager e Lazy - Hibernate

    SAlve a tutti,
    sto cercando di capire in dettaglio la differnza tra eager e lazy.
    Dai vari manuali mi sembra di capire volendo sintetizzare che eager carica tutti i dati
    di una relazione uno a molti in una classe, lazy non carica i dati della tabella filgia fino a quando
    non viene richiesto tramite il metodo getOggettoX...

    Poi andando a studiare l'eccezione LazyInitializationException, mi sono sorte un bel po' di perplessità..... sembra che venga sollevata quando la sessione viene chiusa e quindi non è possibile recuperare i dati della tabella figlia utilizzando l'attributo lazy...

    Mi potreste chiarire cortesemente un po' le idee?

    Grazie tante

  2. #2
    In Hibernate è esattamente quello che hai detto tu, cioè se la relazione lazy non viene valorizzata prima che la sessione venga chiusa allora all'accesso a tale proprietà verrà sollevata una LazyInitializationException.
    Qui trovi un semplice esempio.

  3. #3
    Utente di HTML.it
    Registrato dal
    May 2010
    Messaggi
    457
    Scusami,
    quando dichiaro una relazione di tipo lazy,
    nel metodo getOggettoX bisogna ricollegarsi al database... ?
    Oppure ci pensa Hibernate?

    L'eccezione sopracitata come si risolve ?

    Ogni volta che si usa lazy si ottiene sempre questa eccezione? Oppure ci sono dei casi in cui va bene?

  4. #4
    Hai due modi per risolverla mantenendo il fetch lazy:
    1) Come mostrato nell'esempio ti tieni traccia della sessione e prima di chiuderla richiami il getXXX della tua property
    2) Imposti la query in modo che effettui il fetch di quella relazione.
    Questo è un esempio di valorizzazione della relazione tramite query:
    codice:
    @Entity
    @Table(name = 'CHILD')
    @NamedQuery(name = 'findChildByName', query = 'select DISTINCT(chd) from Child chd left join fetch chd.toyList where chd.childName=:chdName')
    public class Child {
    
     public static interface Constants {
      public static final String FIND_CHILD_BY_NAME_QUERY = 'findChildByName';
    
      public static final String CHILD_NAME_PARAM = 'chdName';
     }
    
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     /**
      * The primary key of the CHILD table
      */
     private Long childId;
    
     @Column(name = 'CHILD_NAME')
     /**
      * The name of the child
      */
     private String childName;
    
     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
     /**
      * The toys the child has. We do not want the child to have the same toy more than
      * once, so we have used a set here.
      */
     private Set<Toy> toyList = new HashSet<Toy>();
    
     public Long getChildId() {
      return childId;
     }
    
     public void setChildId(Long childId) {
      this.childId = childId;
     }
    
     public String getChildName() {
      return childName;
     }
    
     public void setChildName(String childName) {
      this.childName = childName;
     }
    
     public Set<Toy> getToyList() {
      return toyList;
     }
    
     public void addToy(Toy toy) {
      toyList.add(toy);
     }
    
    }
    Il "trucco" sta nelle parole chiave "left join fetch chd.toyList" dove dico di valorizzare la lista dei giocattoli.

  5. #5
    Utente di HTML.it
    Registrato dal
    May 2010
    Messaggi
    457
    Originariamente inviato da francesco.muia
    Hai due modi per risolverla mantenendo il fetch lazy:
    1) Come mostrato nell'esempio ti tieni traccia della sessione e prima di chiuderla richiami il getXXX della tua property
    2) Imposti la query in modo che effettui il fetch di quella relazione.
    Questo è un esempio di valorizzazione della relazione tramite query:
    codice:
    @Entity
    @Table(name = 'CHILD')
    @NamedQuery(name = 'findChildByName', query = 'select DISTINCT(chd) from Child chd left join fetch chd.toyList where chd.childName=:chdName')
    public class Child {
    
     public static interface Constants {
      public static final String FIND_CHILD_BY_NAME_QUERY = 'findChildByName';
    
      public static final String CHILD_NAME_PARAM = 'chdName';
     }
    
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     /**
      * The primary key of the CHILD table
      */
     private Long childId;
    
     @Column(name = 'CHILD_NAME')
     /**
      * The name of the child
      */
     private String childName;
    
     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
     /**
      * The toys the child has. We do not want the child to have the same toy more than
      * once, so we have used a set here.
      */
     private Set<Toy> toyList = new HashSet<Toy>();
    
     public Long getChildId() {
      return childId;
     }
    
     public void setChildId(Long childId) {
      this.childId = childId;
     }
    
     public String getChildName() {
      return childName;
     }
    
     public void setChildName(String childName) {
      this.childName = childName;
     }
    
     public Set<Toy> getToyList() {
      return toyList;
     }
    
     public void addToy(Toy toy) {
      toyList.add(toy);
     }
    
    }
    Il "trucco" sta nelle parole chiave "left join fetch chd.toyList" dove dico di valorizzare la lista dei giocattoli.
    Ma allora a questo punto uso la property EAGER.... ti pare? Che differnza c'è?

  6. #6
    La differenze è che nelle altre query non ti viene valorizzata quella relazione e direi che è una differenza sostanziale.

  7. #7
    Utente di HTML.it
    Registrato dal
    May 2010
    Messaggi
    457
    Originariamente inviato da francesco.muia
    La differenze è che nelle altre query non ti viene valorizzata quella relazione e direi che è una differenza sostanziale.
    Con eager la query tira fuori tutti i dati, potresti spiegarti meglio? Perdonami, è un concetto troppo complicato per me...
    Grazie 1000

  8. #8
    Allora supponiamo che tu hai un entity "Maestra" che ha una relazione uno-a-molti (oneToMany) con l'entity "Alunni" (una maestra insegna in più classi quindi gli alunni sono molti).
    Supponi di voler trovare il nome della Maestra di cognome Rossi, scriverai + o - questa query
    codice:
    SELECT M from Maestra M where M.cognome = :cognome
    Se la relazione alunni è LAZY allora hibernate effettuerà esattamente la query cosi com'è
    Se la relazione invece è EAGER allora farà, in base al FetchStrategy impostato, ho una seconda query :
    codice:
    Select A.* from Maestra M, Alunni A where A.maestraId = M.id and M.id = <id che viene fuori dalla prima select>
    per valorizzare la relazione oppure un join cioè:
    codice:
    SELECT M,A from Maestra M,Allunni A where M.cognome = :cognome and A.maestraId = M.id
    quindi in poche parole tutte le proprietà e relazioni EAGER vengono valorizzate a prescindere dalla query che stai effettuando.

  9. #9
    Utente di HTML.it
    Registrato dal
    May 2010
    Messaggi
    457
    @NamedQuery(name = 'findChildByName', query = 'select DISTINCT(chd) from Child chd left join fetch chd.toyList where chd.childName=:chdName')


    Mi spieghi un po' questa sintassi?

    con "from Child chd left join fetch chd.toyList" sto mettendo in join la tabella Child con La tabella Toys?

    Quanto alla prima soluzione 1) Come mostrato nell'esempio ti tieni traccia della sessione e prima di chiuderla richiami il getXXX della tua property - l'esempio sottostante potrebbe essere quello giusto?

    codice:
    User user = (User) session.createCriteria(User.class)
                    .setFetchMode("permissions", FetchMode.JOIN)
                    .add( Restrictions.idEq(userId) )
                    .uniqueResult();

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.