Spring + Hibernate Lazy Load Ошибка - PullRequest
       1

Spring + Hibernate Lazy Load Ошибка

5 голосов
/ 02 августа 2011

У меня странная ситуация, когда у меня возникает проблема с отложенной загрузкой на одном из моих контроллеров. Примечание: я использую OpenSessionInViewInterceptor и аннотирую свой «сервисный» слой как транзакционный.

У меня есть несколько различных способов загрузить объект Person, один по его ключу и один поего SSN.На моем объекте person у меня есть коллекция ролей, в которых я лениво загружаюсь. Когда я загружаюсь с помощью ключа, я могу получить доступ к списку, как и ожидалось.Когда я загружаюсь по SSN, я не могу получить доступ к списку.

В моем файле конфигурации уровня обслуживания я добавил:

<tx:annotation-driven />

Вот часть моего уровня обслуживания, которая загружает человекапо ключу и SSN (я знаю, что это должно быть в DAO / реструктурировано - это унаследованный код) - Обратите внимание, что ни одна из версий в SSN не допускает загрузку - обе находятся в одном классе:

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

Единственная разница в моих контроллерах - это одна загрузка по ключу и одна загрузка по SSN.Вот соответствующая часть трассировки стека:

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)

Странное примечание: если я загружаю человека по ключу сразу после загрузки по SSN, я могу читать коллекцию без проблем.

Редактировать:

Вот журналы до трассировки стека:

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!

1 Ответ

2 голосов
/ 02 августа 2011

Вы не показали достаточно стека трассировки, чтобы увидеть, откуда исходит исключение, но я предполагаю, что оно находится на вашем уровне представления.Вот что такое открытый сеанс в представлении.Вы говорите, что используете OpenSessionInViewInterceptor, но, по-видимому, недостаточно широко его расширяете.Перехватчик применяется к вызовам методов.Я собираюсь догадаться, что вы применили это к своим "услугам".Если это так, вы можете просто выключить его.Это ничего не делает для вас вообще.Весь смысл шаблона в том, чтобы сеанс оставался открытым за пределами границы уровня обслуживания.Для типичного веб-приложения подходящий выбор - OpenSessionInViewFilter .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...