How to test whether lazy loaded JPA collection is initialized?

微笑、不失礼 提交于 2019-12-17 17:39:04

问题


I have a service that gets a JPA entity from outside code. In this service I would like to iterate over a lazily loaded collection that is an attribute of this entity to see if the client has added something to it relative to the current version in the DB.

However, the client may have never touched the collection so it's still not initialized. This results in the well known

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

Of course, if the client never touched the collection, my service doesn't have to check it for possible changes. The thing is that I can't seem to find a way to test whether the collection is initialized or not. I guess I could call size() on it and if it throws LazyInitializationException I would know, but I'm trying not to depend on such patterns.

Is there some isInitialized() method somewhere?


回答1:


Are you using JPA2?

PersistenceUnitUtil has two methods that can be used to determine the load state of an entity.

e.g. there is a bidirectional OneToMany/ManyToOne relationship between Organization and User.

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();
}



回答2:


org.hibernate.Hibernate.isInitialized(..)

There is no standard JPA solution to my knowledge. But if you want to actually initialize collections, you can create an utility method and iterate them (only one iteration is enough).




回答3:


As the other poster indicates, Hibernate has a method for this. However, there is no solution for this in pure JPA.




回答4:


For eclipselink, users cast the collection you are trying to access to an org.eclipse.persistence.indirection.IndirectList, and then call its isInstantiated() method. The following link has more information:

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



来源:https://stackoverflow.com/questions/4306463/how-to-test-whether-lazy-loaded-jpa-collection-is-initialized

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!