How to test whether lazy loaded JPA collection is initialized?

JavaHibernateJpaLazy Loading

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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).

Solution 3 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionakiraView Question on Stackoverflow
Solution 1 - JavadiraView Answer on Stackoverflow
Solution 2 - JavaBozhoView Answer on Stackoverflow
Solution 3 - JavaamaxView Answer on Stackoverflow