Lazy loading outside of transaction


#1

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

#2

Just change this:

for(int i = 0; i < 5; i++) {
    dave = someAccess(i==0);
}

to this:

dave = someAccess(false);

And you should see the exception thrown.


#3

Yes I get that, but the question is what was the original attempt by the original developers, how did they expect to get the lazyexception without closing the session? That made me wonder if Hibernate back in the 3.x days actually didn’t let you lazy fetch outside the transaction.


#4

I can’t speak in the name of other devs. The code keeps on changing, tests too. You should work using the latest Hibernate ORM code, which I know better than 4.x and way better than 3.x.


#5

I would, but the company that is hosting the thesis uses this version so I have to adapt to that unfortunately :wink: