2010-08-17 5 views
4
MyObject myObject = repositoryHibernateImpl.getMyObjectFromDatabase(); 
//transaction is finished, and no, there is not an option to reopen it 
ThirdPartyUtility.doStuffWithMyObjectType(myObject); 

à ce stade, vous avez déjà défini ce qui est paresseux et désireux chargé, et l'utilitaire tiers essayerez d'appeler toutes les méthodes de votre « myObject » par exemple, c'est bien parce que vous ne voulez pas retourner quoi que ce soit pour les propriétés paresseusement chargées, malheureusement, il ne renvoie pas de valeur nulle, il lance un LazyInitializationException.Mise en veille prolongée - Éviter LazyInitializationException - Détachez objet à partir de Proxy et session

Cela se produit parce que vous appelez en fait la méthode sur le proxy de mise en veille prolongée de votre objet, et il sait qu'il n'a pas tiré par les cheveux que les données, et génère une exception.

Est-il même possible d'obtenir l'objet sous-jacent avec des valeurs nulles de sorte qu'un getter retourne juste nulle, et ne jette pas une exception? Fondamentalement, détacher l'objet de sorte qu'Hibernate n'en soit plus du tout conscient. L'accesseur à l'objet qui est paresseusement chargé doit retourner null, il ne peut pas retourner les valeurs réelles, nous voulons être en mesure de convertir l'entité en POJO sans avoir à créer un objet qui ressemble à l'entité et doit remapper tous les valeurs.

Répondre

2

Disons que vous avez un champ, dans le getter, vous pouvez:

MyField getMyField() { 
    if (Hibernate.isInitialized(myField)) { 
     return myField; 
    } 
    return null; 
} 

De la javadoc de org.hibernate.Hibernate:

statique public boolean isInitialized (proxy Object): vérifier si le proxy ou la collection persistante est initialisé.

+0

c'est une solution très intéressante, il y a évidemment un inconvénient que l'entité devient étroitement couplée à hiberner, mais à moins qu'il y ait une réponse qui le fait sans le couplage je pense que c'est le gagnant – walnutmon

0

Si vous ne voulez pas coupler votre domaine hiberner, une autre possibilité est d'avoir votre DAO instancier votre propre instance de l'entité à l'intérieur getMyObjectFromDatabase() et remplir que les champs appropriés de proxy de mise en veille prolongée. J'ai fait ça et ça marche bien.

Évidemment, cela est plus de code, mais vous garanti une instance « pure » de votre entité (avec des valeurs non initialisées nulles) si c'est ce que vous voulez.

0

vérifiez ma solution.

exemple minimal:

Je ne charge pas la propriété de l'objet, mais du contrôleur.
code:

{..} 

MyProp prop = employeeController.getMyProp(employee); 

{..} 

Cette initiaqlizes la propriété via l'objet de dépôt et le renvoie.
EmployeeController.java:

public Set<MyProp> getMyProp(Employee employee) { 

    if (this.employeeRepository.InitMyProp(employee)){ 

     return employee.getMyProp(); 
    } 

    return null; 
} 

Repository get/ouvrir la session, reload objet employé! et initialiser le terrain chargé paresseux
EmployeeRepository.java:

public boolean InitMyProp(Employee employee) { 

    if (Hibernate.isInitialized(employee.getMyProp())){ 
     return true; 
    } 

    try { 
     Session session = getSession(); 

     session.refresh(employee); 

     Hibernate.initialize(employee.getMyProp()); 

    } catch (Exception ex) { 
     return false; 
    } 

    return true; 
} 

private Session getSession(){ 

    if (session == null || !session.isConnected() || !session.isOpen()){ 
     session = HibernateUtil.getSessionFactory().getCurrentSession(); 
    } 
    if (!session.getTransaction().isActive()) { 
     session.beginTransaction(); 
    } 
    return session; 
} 

J'ai dans ma solution un TableView avec plusieurs milliers de documents et 2 autres TableViews avec des détails sur l'enregistrement sélectionné dans la première TableView.
espérons que ça aide.

+0

Pourquoi cela résout-il le problème? Pouvez-vous améliorer la qualité de votre réponse ** en éditant votre message et en fournissant plus d'informations sur votre code **? –