Чтобы сессия Hibernate не заканчивалась с помощью аннотаций? - не удалось лениво инициализировать коллекцию ролей - PullRequest
0 голосов
/ 11 июня 2011

У меня есть спящий DAO, который выдает исключение «не удалось лениво инициализировать коллекцию ролей» при попытке доступа к члену возвращенного объекта, который является сумкой / коллекцией.

Я понимаю масштабы проблемы, вызывающей исключение. Hibernate возвращает мой объект, а для любых коллекций возвращает прокси-объекты. В моем звонящем, когда я обращаюсь к этим прокси-объектам, , поскольку сеанс гибернации истек , это исключение выдается.

Что я хочу знать, как я могу предотвратить истечение сеанса , используя аннотации ? Возможно ли это?

Например, если мой вызывающий метод:

@RequestMapping("refresh.url")
public ModelAndView refresh(HttpServletRequest request, HttpServletResponse response, int id) throws Exception {
    TestObject myObj = testObjDao.get(id);
    // throws the exception
    myObj.getCollection();

Как бы я мог предотвратить это исключение, используя аннотации? Я знаю, что одним из решений было бы расширить сеанс гибернации с помощью обратного вызова, который в псевдокоде может выглядеть примерно так:

@RequestMapping("refresh.url")
public ModelAndView refresh(HttpServletRequest request, HttpServletResponse response, int id) throws Exception {
    session = get hibernate session...
    session.doInSession(new SessionCallback() {
        TestObject myObj = testObjDao.get(id);
        // no longer throws the exception
        myObj.getCollection();
    });

но это кажется довольно повторяющимся во всех моих функциях, которые нужны для доступа к коллекциям. разве нет способа просто добавить аннотацию @Transactional и покончить с этим? как в:

@RequestMapping("refresh.url")
@Transactional  // this doesn't extend the session to this method?
public ModelAndView refresh(HttpServletRequest request, HttpServletResponse response, int id) throws Exception {
    TestObject myObj = testObjDao.get(id);
    // throws the exception
    myObj.getCollection();

спасибо за вашу помощь в объяснении этого мне.

Ответы [ 3 ]

1 голос
/ 12 июня 2011

Hibernate-сессии отличаются от веб-сессий и не имеют срока действия.Они закрываются либо вручную вашим кодом, либо инфраструктурой (например, Spring).

В вашем случае неясно, как ваш сеанс создается в первую очередь, поскольку, если вы введете DAO без сеанса, вы получите совершенно другое исключение (No Session Bound to Thread).Итак, как-то ваша сессия создается и закрывается.Мое предположение состоит в том, что ваш DAO делается транзакционным либо через @Transactional, либо через перехватчики, поэтому сеанс инициируется при его вводе и закрывается при выходе из метода DAO.В этом случае установка @Transactional на метод MVC будет работать до тех пор, пока для распространения транзакций в DAO установлено значение PROPAGATION_REQUIRED.

Однако имейте в виду, что вы не можете вынести свою коллекцию за пределыметода аннотируется через @Transactional.Например, вы не должны помещать это в сессию http.Если это требование, вы можете использовать специальные объекты DTO для копирования данных.

1 голос
/ 11 июня 2011

Вам необходимо сделать следующее:

1) Пусть Spring управляет вашей транзакцией:

Подробнее об этом можно прочитать здесь: http://www.mkyong.com/spring/spring-aop-transaction-management-in-hibernate/

и здесь:

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative

2) Теперь ленивая загрузка:

Когда вы выбираете объект из Hibernate, все его ленивые ассоциации возвращаются в качестве прокси, а затем при доступе к классам прокси вы получаете исключение, потому что ваш сеанс Hibernate закрыт.

Решением является использование открытого сеанса в представлении фильтра / перехватчика.

http://www.paulcodding.com/blog/2008/01/21/using-the-opensessioninviewinterceptor-for-spring-hibernate3/

это будет выглядеть именно так:

<mvc:interceptors>
<bean class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
</mvc:interceptors>

Надеюсь, это поможет.

0 голосов
/ 23 июля 2011

Я решил использовать аннотацию @LazyCollection для коллекции в DAO.

@OneToMany(mappedBy = "<something here>", cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
...