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

Java EE Discussion :

Failed to lazily initialize a collection of role: metier.entities.Product.items, no session or session was clo


Sujet :

Java EE

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 66
    Points : 42
    Points
    42
    Par défaut Failed to lazily initialize a collection of role: metier.entities.Product.items, no session or session was clo
    Bonjour à tous,

    Je travaille sur un projet, j'ai trois 3 classes: Category, Praoduct et item qui s'associent de la manière suivante:

    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
     
    @Entity
    @Table(name="Category")
    public class Category implements Serializable {
    	@Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
        @Column(nullable=false, length=30)
        private String name;
        @Column(nullable=false)
        private String description;
        @OneToMany(mappedBy="category", cascade= CascadeType.REMOVE, fetch= FetchType.EAGER)
        @OrderBy("name ASC")
        private List<Product> products;
     
    // getter and setter
    }
    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
     
    @Entity
    @Table(name="Product")
    public class Product implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
        @Column(nullable=false, length=30)
        private String name;
        @Column(nullable=false)
        private String description;
        @ManyToOne(fetch= FetchType.EAGER)
        @JoinColumn(name="category_fk", nullable=false)
        private Category category;
        @OneToMany(mappedBy="product", cascade= CascadeType.REMOVE, fetch=FetchType.LAZY)
        @OrderBy("name ASC")
        private List<Item> items;
     
    //getter and setter
    }
    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
     
    @Entity
    @Table(name="Item")
    public class Item implements Serializable {
    	@Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
        @Column(nullable=false, length=30)
        private String name;
        @Column(name="unit_cost", nullable=false)
        private Float unitCost;
        @Column(name="image_path")
        private String imagePath;
     
        @ManyToOne(fetch= FetchType.EAGER)
        @JoinColumn(name="product_fk", nullable=false)
        private Product product;
    Une EJB Session:
    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
     
    @Stateless
    public class CatalogueEJB implements ICategoryLocal, ICategoryRemote {
        @PersistenceContext(unitName="UP_PET")
        private EntityManager em;
     
        @Override
        public List<Product> findProducts() {
     
            Query query;
            List<Product> products;
     
            query = em.createQuery("SELECT p FROM Product p ORDER BY p.name");
            products = query.getResultList();
            return products;
        }
     
        @Override
        public Item findItem(final Long itemId) {  
            if(itemId == null)
                throw new ValidationException("Identifiant invalide");
     
            Item item = em.find(Item.class, itemId);
            return item;
        }
     
        @Override
        public List<Item> findItems() {      
            Query query = em.createQuery("SELECT i FROM Item i ORDER BY i.name");
     
            List<Item> items = query.getResultList();
            return items;     
        }
    Un ManageBean:
    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
     
    public class CatalogController {
        @EJB
        private ICategoryLocal catalogBean;
        private String keyword;
        private Category category = new Category();
        private Product product = new Product();
        private Item item;
        private List<Product> products;
        private List<Item> items;
     
        public CatalogController() {
     
        }
     
        public String doFindProducts() {
     
            final String mname = "doFindProducts";
            logger.entering(cname, mname);
            String navigateTo = null;
     
            try {
                category = catalogBean.findCategory(getParamId("categoryId"));
                products = category.getProducts();
     
            } catch(Exception e) {
                addMessage(e);
            }
     
            return "products.displayed";
        }
     
        public String doFindItems() {
     
            String navigateTo = null;
     
            try {
                product = catalogBean.findProduct(getParamId("productId"));
                items = product.getItems();
                navigateTo = "items.displayed";
     
            }catch(Exception e) {
                addMessage(e);
            } 
            return navigateTo;
        }
     
        public String doFindItem() {
     
            String navigateTo = null;
            try {
                item = catalogBean.findItem(getParamId("itemId"));
                navigateTo = "item.displayed";  
            } catch(Exception e) {
                addMessage(e);
            }
            return navigateTo;
     
        }
    // getter and setter
    }
    Dans la partie Vue, j'utilise JSP et JSF. Lorsque je veux afficher la liste des tous les produits, cela fonctionne nikel
    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
     
     
                <h2>Products for category :
                    <h:outputText value="#{catalog.category.name}"/>
                </h2>
     
     <h:form>
                    <h:dataTable value="#{catalog.products}" var="product">
                        <h:column>
                            <h:commandLink action="#{catalog.doFindItems}">
                                <h:outputText value="#{product.name}"/>
                                <f:param name="productId" value="#{product.id}"/>
                            </h:commandLink>
                            <br/>
                            <h:outputText value="#{product.description}"/>
                        </h:column>
                    </h:dataTable>
                </h:form>
    Mais en cliquant sur un produit pour afficher sa liste des items,
    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
     
               <h2>Items for product :
                    <h:outputText value="#{catalog.product.name}"/>
               </h2>
     
                <h:form>
                    <h:dataTable value="#{catalog.items}" var="item">
                        <h:column>
                            <h:commandLink action="#{catalog.doFindItem}">
                                <h:outputText value="#{item.name}"/>
                                <f:param name="itemId" value="#{item.id}"/>
                            </h:commandLink>
                        </h:column>
     
                        <h:column>
                            <h:outputText value="#{item.unitCost}"/>
                            $
                        </h:column>
                  </h:dataTable>
                </h:form>
    cela génère le message d'erreur suivant: javax.servlet.ServletException: failed to lazily initialize a collection of role: metier.entities.Product.items, no session or session was closed javax.faces.webapp.FacesServlet.service(FacesServlet.java:606).
    Je remercie d'avantage pour votre aide car ça fait plusieurs que je suis bloqué à ce problème. Merci!

  2. #2
    Membre actif
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2014
    Messages
    153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mai 2014
    Messages : 153
    Points : 227
    Points
    227
    Par défaut
    Change ton fetch.type.eager par lazy et ton cascade par .all.
    Bonne continuation.

  3. #3
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Dans ta classe Product, tu as mis la relation OneToMany en Lazy.
    Ta requête "query = em.createQuery("SELECT p FROM Product p ORDER BY p.name");" s'occupe de charger la liste des "Product" mais sans s'occuper d'autre chose.
    Avec les EJB, lorsque tu sors du conteneur (d'EJB), les entity sont détachées, du coup, toutes les propriétés en lazy loading n'ayant pas été chargées seront inaccessibles, d'où ton erreur.

    Tu as plusieurs possibilités pour régler ton problème :

    - tu changes le FetchType.Lazy en EAGER (dans Product, pour le mapping de la relation Item)
    - tu changes ta requête en "select p from Product p join fetch p.items order by p.name"
    - tu lis le résultat de ta requête et tu accèdes à items comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for (Product product : query.getResultList())
    {
       product.getItems().size();
    }
    ce qui lancera les requêtes nécessaires...

    La meilleure solution dépend un peu du besoin fonctionnel. Si un "Product" ne peut se voir sans ses "Item", il vaudrait mieux déclarer la relation en EAGER.
    Sinon, utilise join fetch (ou left join fetch si tu n'as pas forcément d'Item pour un Product)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. Réponses: 10
    Dernier message: 07/03/2014, 16h18
  2. Failed to lazily initialize a collection
    Par Grumium dans le forum Hibernate
    Réponses: 8
    Dernier message: 27/10/2009, 16h35
  3. Réponses: 5
    Dernier message: 23/10/2009, 14h02
  4. failed to lazily initialize a collection of role ?
    Par zuzuu dans le forum Hibernate
    Réponses: 3
    Dernier message: 25/02/2009, 16h02
  5. Réponses: 1
    Dernier message: 04/04/2007, 09h17

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