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
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:
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
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".
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
.
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)
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.
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")
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
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.
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_
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
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
utilise session.obtenir.*(class, id); mais ne pas charger la fonction
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
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>