2011-08-02 13 views
5

Tengo una situación extraña en la que tengo un problema de carga lenta en uno de mis controladores. Nota: Estoy usando OpenSessionInViewInterceptor y estoy anotando mi capa de "servicio" como transaccional.Spring + Hibernate Error de carga diferida

Tengo un par de formas diferentes de cargar un objeto Person, una por su clave y una por su SSN. En mi objeto personal, tengo una colección de roles en los que cargo lentamente. Cuando cargo con la clave, puedo acceder a la lista como se espera. Cuando cargo el SSN, no puedo acceder a la lista.

En mi archivo de configuración del servicio de la capa I han añadido:

<tx:annotation-driven /> 

Aquí es mi pieza capa de servicio que carga la persona por Key & SSN (sé que esto tiene que estar en un DAO/reestructurado - este código es heredado) - Nota ninguna de las versiones de la pieza SSN permite la carga - ambos son de la misma clase:

@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; 
} 

la única diferencia en mis reguladores es uno cargas por clave, las cargas y uno por el SSN. Aquí está la parte pertinente de la 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) 

tono extraño, si me carga la persona con la tecla inmediatamente después de la carga por la SSN, soy capaz de leer la colección sin problema.

Editar:

Éstos son los registros anteriores a la traza de la pila:

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! 
+0

Además, si llamo a Hibernate.initialize (persona) aún obtengo la excepción de inicialización, incluso si hago eso en la capa de servicio. – Scott

Respuesta

2

Usted no mostraron suficiente de la StackTrace para ver donde la excepción está viniendo, pero supongo que es en tu capa de vista. De eso se trata el patrón de sesión abierta a la vista. Usted dice que está usando OpenSessionInViewInterceptor, pero aparentemente no le está dando un alcance lo suficientemente amplio. El interceptor se aplica a llamadas de método. Voy a adivinar que lo has aplicado a tus "servicios". Si es así, también puedes apagarlo. No está haciendo nada por ti en absoluto. El objetivo de este patrón es garantizar que la sesión permanezca abierta más allá de el límite de la capa de servicio. Para una aplicación web típica, OpenSessionInViewFilter es la opción adecuada.

+0

Se agregaron las siguientes dos líneas de seguimiento de la pila. Definitivamente no está sucediendo dentro de la vista. – Scott

+0

@Scott: Agrupe los controladores en "ver". ¿Dónde se aplica OpenSessionInViewInterceptor? –

+0

Usando el estándar OpenSessionInViewInterceptor. Se aplica a todas las solicitudes que se manejan a través del Servlet de Dispatcher. Cuando depuro a través de controladores en funcionamiento y controladores que no funcionan, veo que hay una sesión que el Interceptor está utilizando. Sin embargo, algo debe estar mal configurado, ya que las Colecciones persistentes que Hibernate envuelve mis colecciones cargadas de forma perezosa no muestran sesión cuando se depuran. – Scott