web-dev-qa-db-fra.com

Comment tester si la collection JPA chargée paresseuse est initialisée?

J'ai un service qui obtient une entité JPA du code extérieur. Dans ce service, je voudrais parcourir une collection chargée paresseusement qui est un attribut de cette entité pour voir si le client y 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, elle n'est donc toujours pas initialisée. Il en résulte le bien connu

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 n'a pas à la vérifier pour d'éventuelles modifications. 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?

46
akira

Utilisez-vous JPA2?

PersistenceUnitUtil a deux méthodes qui peuvent être utilisées pour déterminer l'état de chargement 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();
}
55
dira
org.hibernate.Hibernate.isInitialized(..)

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

25
Bozho

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

2
robertgoko

Pour eclipselink, les utilisateurs transtypent la collection à laquelle vous essayez d'accéder à un org.Eclipse.persistence.indirection.IndirectList, Puis appellent sa méthode isInstantiated(). Le lien suivant contient plus d'informations:

http://www.Eclipse.org/eclipselink/api/1.1/org/Eclipse/persistence/indirection/IndirectList.html#isInstantiated .

2
amax