Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring + Hibernate Lazy Load Error

I'm having an odd situation where I am getting a lazy loading issue on one of my controllers. Note: I am using the OpenSessionInViewInterceptor and am annotating my "service" layer as Transactional.

I have a couple of different ways to load a Person object, one by its key and one by its SSN. On my person object I have a collection of roles which I lazily load in. When I load by the Key, I am able to access the list as expected. When I load by the SSN, I am unable to access the list.

In my service layer configuration file I have added:

<tx:annotation-driven />

Here is my service layer piece which loads the person by Key & SSN (I know this needs to be in a DAO / restructured -- this is inherited code) -- Note neither version in the SSN piece allows the loading -- both are in the same class:

@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Person loadPersonByKey(final Person.Key personKey) {
    Assert.notNull(personKey);
    return (Person) getHibernateTemplate().get(Person.class, personKey);
} 

@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public Person findPersonBySsn(final SocialSecurityNumber ssn) {

    @SuppressWarnings("unchecked")
    //List<Person> results = getHibernateTemplate().findByNamedParam("from core.model.entities.Person as person where ssn = :ssn", "ssn", ssn);

    Criteria crit = getSession().createCriteria(Person.class);
    crit.add(Restrictions.eq("ssn", ssn));
    List<Person> results = crit.list();

    int size = results.size();

    Person returnPerson = ((size != 0) ? (Person) results.get(0) : null);
    return returnPerson;
}

The only difference in my controllers is one loads by Key, and one loads by SSN. Here is the pertinent portion of the stacktrace:

SEVERE: Servlet.service() for servlet springmvc threw exception
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: core.model.entities.Person.memberships, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:176)
at org.hibernate.collection.PersistentMap.get(PersistentMap.java:169)
at core.model.entities.Person.getMemberships(Person.java:870)
at core.springmvc.controllers.find.FindController.defaultAction(FindController.java:164)

Odd note, if I load the person by key immediately after loading by the SSN, I'm able to read the collection without issue.

Edit:

Here are the logs prior to the stack trace:

2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.springframework.jdbc.datasource.DataSourceUtils CV#905cde28-e60c-4331 P#75004 - Resetting read-only flag of JDBC Connection [Transaction-aware proxy for target Connection [jdbc:oracle:thin:@(description=(address_list=(address=(host=127.0.0.1)(protocol=tcp)(port=11523))(load_balance=yes)(failover=yes))), UserName=USER_NAME, Oracle JDBC driver]]
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.impl.SessionImpl CV#905cde28-e60c-4331 P#75004 - disconnecting session
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.jdbc.ConnectionManager CV#905cde28-e60c-4331 P#75004 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.springframework.jdbc.datasource.DataSourceUtils CV#905cde28-e60c-4331 P#75004 - Returning JDBC Connection to DataSource
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.jdbc.ConnectionManager CV#905cde28-e60c-4331 P#75004 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
like image 950
Scott Avatar asked Nov 05 '22 17:11

Scott


1 Answers

You didn't show enough of the stacktrace to see where the exception is coming from, but I assume it's in your view layer. That's what the open session in view pattern is about. You say you're using the OpenSessionInViewInterceptor, but apparently you're not giving it a wide enough scope. The interceptor applies to method calls. I'm going to guess that you've applied it to your "services". If so, you might as well just turn it off. It's not doing anything for you at all. The whole point of the pattern is to ensure the Session stays open beyond the service layer boundary. For a typical webapp, the OpenSessionInViewFilter is the appropriate choice.

like image 194
Ryan Stewart Avatar answered Nov 09 '22 16:11

Ryan Stewart