Hi again,
In my migration project I have some old tests that the old developers used (Hibernate 3.2) and in their tests they test whether some associations get lazy loaded and then tries to traverse an entity that is not yet loaded from the DB, expecting a LazyInitializationException. What is strange however, is that they do this procedure inside a session, but outside a transaction. Couldn’t you lazy load associations outside of a transaction in earlier versions of hibernate?
In order to get the exception nowadays you have to close the session right? I am using hibernate 4.3.10 right now and I can lazy load outside of the transaction context. So is this a change in hibernate or is it simply faulty tests from the earlier developers?
They do it like this:
@Test
public void testLoadFetchProfile() {
em.clearExtentInformation();
// Execute query multiple times
Employee dave = null;
for(int i = 0; i < 5; i++) {
dave = someAccess(i==0);
}
// These all should not throw lazy instantiation exception, because
// they should have been fetch eagerly
dave.getSupervisor().getName();
dave.getSupervisor().getSupervisor().getName();
dave.getSupervisor().getSupervisor().getSubordinates().size();
dave.getMentor().getName();
// This should throw a lazy instantiation exception
try {
dave.getSupervisor().getSupervisor().getSupervisor().getName();
// Shouldn't get here
Assert.fail("Lazy instantion exception not thrown for a property which shouldn't have been fetched");
} catch (LazyInitializationException e) {
// Good
}
}
private Employee someAccess(boolean traverse) {
Session sess;
Transaction tx = null;
Long daveId = createObjectGraph(true);
try {
sess = openSession();
tx = sess.beginTransaction();
Employee dave = (Employee) sess.load(Employee.class, daveId);
dave.getName();
if (traverse) {
dave.getSupervisor().getName();
dave.getMentor().getName();
dave.getSupervisor().getSupervisor().getName();
dave.getSupervisor().getSupervisor().getSubordinates().size();
}
tx.commit();
tx = null;
return dave;
} finally {
if (tx != null) {
tx.rollback();
}
}
}