org.hiberner.LazyInitializationException - n'a pas pu initialiser le proxy - pas de Session

j'obtiens l'exception suivante:

Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at sei.persistence.wf.entities.Element_$$_jvstc68_47.getNote(Element_$$_jvstc68_47.java)
    at JSON_to_XML.createBpmnRepresantation(JSON_to_XML.java:139)
    at JSON_to_XML.main(JSON_to_XML.java:84)

quand j'essaie d'appeler des principales lignes suivantes:

Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());

j'ai mis en œuvre la méthode getModelByModelGroup(int modelgroupid) tout d'abord comme ceci:

    public static Model getModelByModelGroup(int modelGroupId, boolean openTransaction) {

        Session session = SessionFactoryHelper.getSessionFactory().getCurrentSession();     
        Transaction tx = null;

        if (openTransaction)
            tx = session.getTransaction();

        String responseMessage = "";

        try {
            if (openTransaction)            
                tx.begin();
            Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
            query.setParameter("modelGroupId", modelGroupId);
            @SuppressWarnings("unchecked")
            List<Model> modelList = (List<Model>)query.list(); 
            Model model = null;
            // Cerco il primo Model che è in esercizio: idwf_model_type = 3
            for (Model m : modelList)
                if (m.getModelType().getId() == 3) {
                    model = m;
                    break;
                }

            if (model == null) {
                Object[] arrModels = modelList.toArray();
                if (arrModels.length == 0) 
                    throw new Exception("Non esiste ");

                model = (Model)arrModels[0];
            }

            if (openTransaction)
                tx.commit();
            return model;

        } catch(Exception ex) {
            if (openTransaction)
                tx.rollback();
            ex.printStackTrace();
            if (responseMessage.compareTo("") == 0)
                responseMessage = "Error" + ex.getMessage();
            return null;        
        }

et j'ai eu l'exception. Puis un ami m'a suggéré de toujours tester la session et obtenir la session actuelle pour éviter cette erreur. Alors j'ai fait ceci:

public static Model getModelByModelGroup(int modelGroupId) {

        Session session = null;
        boolean openSession = session == null;
        Transaction tx = null;
        if (openSession){
          session = SessionFactoryHelper.getSessionFactory().getCurrentSession();   
            tx = session.getTransaction();
        }
        String responseMessage = "";

        try {
            if (openSession)            
                tx.begin();
            Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
            query.setParameter("modelGroupId", modelGroupId);
            @SuppressWarnings("unchecked")
            List<Model> modelList = (List<Model>)query.list(); 
            Model model = null;
            for (Model m : modelList)
                if (m.getModelType().getId() == 3) {
                    model = m;
                    break;
                }

            if (model == null) {
                Object[] arrModels = modelList.toArray();
                if (arrModels.length == 0) 
                    throw new RuntimeException("Non esiste");

                model = (Model)arrModels[0];

            if (openSession)
                tx.commit();
            return model;

        } catch(RuntimeException ex) {
            if (openSession)
                tx.rollback();
            ex.printStackTrace();
            if (responseMessage.compareTo("") == 0)
                responseMessage = "Error" + ex.getMessage();
            return null;        
        }

    }

mais toujours la même erreur. Je ont beaucoup lu pour cette erreur et ont trouvé des solutions possibles. L'un d'eux était de mettre lazyLoad à false mais je ne suis pas autorisé à faire cela c'est pourquoi on m'a suggéré de contrôler la session

118
demandé sur Rubens Mariuzzo 2014-02-05 14:12:21

15 réponses

ce qui ne va pas ici, c'est que votre configuration de gestion de session est définie pour fermer la session lorsque vous commettez une transaction. Vérifiez si vous avez quelque chose comme:

<property name="current_session_context_class">thread</property> 

dans votre configuration.

pour surmonter ce problème, vous pouvez modifier la configuration de session factory ou ouvrir une autre session et seulement demander ces objets chargés paresseux. Mais ce que je suggère ici est d'initialiser cette collection paresseuse dans getModelByModelGroup lui-même et appeler:

Hibernate.initialize(subProcessModel.getElement());

quand vous êtes encore en session active.

Et une dernière chose. Un conseil amical. Vous avez quelque chose comme ceci dans votre méthode:

            for (Model m : modelList)
            if (m.getModelType().getId() == 3) {
                model = m;
                break;
            }

s'il vous plaît insté de ce code il suffit de filtrer les modèles avec un id de type égal à 3 dans la déclaration de requête juste quelques lignes ci-dessus.

un peu plus de lecture:

session configuration de l'usine

problème avec fermeture de session

63
répondu goroncy 2014-02-05 11:01:45

vous pouvez essayer de définir

<property name="hibernate.enable_lazy_load_no_trans">true</property>

en hibernation.cfg.xml ou de la persistance.xml

le problème à garder à l'esprit avec cette propriété sont bien expliqués ici

91
répondu Wilianto Indrawan 2017-05-23 12:02:59

si vous utilisez Spring marquer la classe comme @Transactional , alors Spring gérera la gestion de session.

@Transactional
public class My Class {
    ...
}

en utilisant @Transactional , de nombreux aspects importants tels que la propagation des transactions sont traités automatiquement. Dans ce cas, si une autre méthode transactionnelle est appelée la méthode aura l'option de rejoindre la transaction en cours en évitant l'exception "pas de session".

69
répondu user2601995 2015-08-28 17:45:37

la meilleure façon de manipuler le LazyInitializationException est d'utiliser la JOIN FETCH directive:

Query query = session.createQuery(
    "from Model m " +
    "join fetch m.modelType " +
    "where modelGroup.id = :modelGroupId"
);

de toute façon, N'utilisez pas les anti-modèles suivants comme suggéré par certaines des réponses:

parfois, un projection DTO est un meilleur choix que de chercher des entités, et de cette façon, vous n'obtiendrez pas de LazyInitializationException .

33
répondu Vlad Mihalcea 2018-01-04 11:55:32

j'avais la même erreur pour un de nombreuses relations pour l'annotation ci-dessous.

@OneToMany(mappedBy="department", cascade = CascadeType.ALL)

modifié comme ci-dessous après avoir ajouté fetch=FetchType.EAGER, ça a marché pour moi.

@OneToMany(mappedBy="department", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
7
répondu Smruti R Tripathy 2017-11-30 18:18:02

cette exception en raison de quand vous appelez session.getEntityById() , la session sera fermée. Vous devez donc rattacher l'entité à la session. Ou la solution facile est juste configurer default-lazy="false" à votre entity.hbm.xml ou si vous utilisez des annotations juste ajouter @Proxy(lazy=false) à votre classe d'entity.

5
répondu Reddeiah Pidugu 2016-09-07 14:37:17

j'ai rencontré le même problème. Je pense qu'une autre façon de corriger ceci est que vous pouvez changer la requête pour rejoindre fetch votre élément de Model comme suit:

Query query = session.createQuery("from Model m join fetch m.element where modelGroup.id = :modelGroupId")
4
répondu Tony Vu 2015-04-13 08:44:41

si vous utilisez spring data jpa , spring boot, vous pouvez ajouter cette ligne dans l'application.propriétés

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
4
répondu Shaaban Ebrahim 2018-06-15 21:24:54

il y a plusieurs bonnes réponses ici qui traitent cette erreur dans une large portée. J'ai rencontré une situation spécifique avec Spring Security qui avait une solution rapide, mais probablement pas optimale.

pendant l'autorisation de l'utilisateur (immédiatement après m'être connecté et avoir passé l'authentification), j'ai testé une entité utilisateur pour une autorité spécifique dans une classe personnalisée qui étend SimpleUrlAuthenticationSuccessHandler.

mon entité utilisateur implements UserDetails et a un ensemble de rôles chargés paresseux qui a jeté le " org.hiberner.LazyInitializationException - ne peut pas initialiser proxy-pas de Session" exception. Changer cet ensemble de " fetch=FetchType.LAZY " to " fetch=FetchType.EAGER " a arrangé ça pour moi.

2
répondu Night Owl 2016-03-15 01:55:36

si vous utilisez JPQL, utilisez JOIN FETCH est le moyen le plus simple: http://www.objectdb.com/java/jpa/query/jpql/from#LEFT_OUTER_INNER_JOIN_FETCH_

1
répondu xihui 2017-03-23 21:55:05

si vous utilisez Grail's Framework, il est simple de résoudre lazy initialization exception en utilisant Lazy mot-clé sur le champ spécifique dans la classe de domaine.

par exemple:

class Book {
    static belongsTo = [author: Author]
    static mapping = {
        author lazy: false
    }
}

trouver des informations supplémentaires ici

0
répondu Zeb 2016-10-27 12:38:04

Cela signifie que l'objet auquel vous tentez d'accéder n'est pas chargé, afin d'écrire une requête qui fait un join fetch de l'objet auquel vous tentez d'accéder.

par exemple:

si vous essayez d'obtenir ObjectB de ObjectA où ObjectB est une clé étrangère dans ObjectA.

Requête :

SELECT objA FROM ObjectA obj JOIN FETCH obj.objectB objB
0
répondu rex roy 2018-04-23 11:36:11

utilise session.obtenir.*(class, id); mais ne pas charger la fonction

-1
répondu Artavazd Manukyan 2015-08-25 21:21:21

vous pouvez également le résoudre en ajoutant lazy=false dans votre *.hbm.le fichier xml ou vous pouvez insérer votre objet dans Hibernate.init (objet) lorsque vous obtenez l'objet de db

-3
répondu Sandeep Roniyaar 2014-07-31 10:12:07

effectuer les changements suivants dans servlet-context.xml

    <beans:property name="hibernateProperties">
        <beans:props>

            <beans:prop key="hibernate.enable_lazy_load_no_trans">true</beans:prop>

        </beans:props>
    </beans:property>
-3
répondu ArunDhwaj IIITH 2016-04-09 00:29:58