2010-11-29 6 views
39

J'ai un service qui obtient une entité JPA de code externe. Dans ce service, je voudrais parcourir une collection chargée paresseusement qui est un attribut de cette entité pour voir si le client a ajouté quelque chose par rapport à la version actuelle dans la base de données. Cependant, le client n'a peut-être jamais touché la collection, ce qui fait qu'elle n'est toujours pas initialisée. Cela se traduit par le bien connuComment tester si la collection JPA chargée paresseuse est initialisée?

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.

Bien sûr, si le client n'a jamais touché la collection, mon service ne doit pas vérifier les changements possibles. Le fait est que je n'arrive pas à trouver un moyen de tester si la collection est initialisée ou non. Je suppose que je pourrais appeler size() dessus et s'il lance LazyInitializationException je le saurais, mais j'essaye de ne pas dépendre de tels modèles.

Existe-t-il une méthode isInitialized() quelque part?

Répondre

48

Utilisez-vous JPA2?

PersistenceUnitUtil a deux méthodes qui peuvent être utilisées pour déterminer l'état de charge d'une entité.

par exemple. Il existe une relation bidirectionnelle OneToMany/ManyToOne entre l'organisation et l'utilisateur.

public void test() { 
    EntityManager em = entityManagerFactory.createEntityManager(); 
    PersistenceUnitUtil unitUtil = 
     em.getEntityManagerFactory().getPersistenceUnitUtil(); 

    em.getTransaction().begin(); 
    Organization org = em.find(Organization.class, 1); 
    em.getTransaction().commit(); 

    Assert.assertTrue(unitUtil.isLoaded(org)); 
    // users is a field (Set of User) defined in Organization entity 
    Assert.assertFalse(unitUtil.isLoaded(org, "users")); 

    initializeCollection(org.getUsers()); 
    Assert.assertTrue(unitUtil.isLoaded(org, "users")); 
    for(User user : org.getUsers()) { 
     Assert.assertTrue(unitUtil.isLoaded(user)); 
     Assert.assertTrue(unitUtil.isLoaded(user.getOrganization())); 
    } 
} 

private void initializeCollection(Collection<?> collection) { 
    // works with Hibernate EM 3.6.1-SNAPSHOT 
    if(collection == null) { 
     return; 
    } 
    collection.iterator().hasNext(); 
} 
+1

Vous avez raison, merci! J'ai oublié de vérifier au débordement de la pile, donc désolé pour l'acceptation tardive. – akira

20
org.hibernate.Hibernate.isInitialized(..) 

Il n'y a pas de solution JPA standard à ma connaissance. Mais si vous voulez réellement initialiser des collections, vous pouvez créer une méthode utilitaire et les itérer (une seule itération suffit).

+1

C'est exactement ce que je cherche, merci! Le problème est que même si je suis en train d'utiliser Hibernate, le code devrait être compatible avec JPA donc malheureusement je ne suis pas vraiment capable d'utiliser ceci :( – akira

+1

il n'y a rien de standard – Bozho

+0

entityManager.find() est assez standard;) différemment, le code devrait également fonctionner sur EclipseLink;) – akira

2

Comme l'indique l'autre affiche, Hibernate a une méthode pour cela. Cependant, il n'y a pas de solution pour cela en pure JPA.

Questions connexes