Отладка Hibernate "Сессия закрыта!" - злоупотребление SSB? - PullRequest
1 голос
/ 10 марта 2011

(Во-первых, это не мой код. Во-вторых, чтобы защитить виновных, я изменил имена классов, чтобы скрыть что-то конкретное для моего работодателя, поэтому, если вещи не соответствуют друг другу, вот почему!).

Может кто-нибудь помочь мне прояснить сомнение, пожалуйста? Меня попросили исследовать проблему с полным пулом соединений, и этот код, кажется, пахнет.

В наших журналах много org.hibernate.SessionException: Session is closed! вокруг следующего кода, который использует пул соединений, который ведет себя плохо.

Звонки поступают через веб-сервис:

1  @Stateless
2  @WebService(name="MyWebService", targetNamespace="http://www.mycompany.com/2010/01/WebService/myWebService")
3  @WebContext(contextRoot="/myContextRoot", secureWSDLAccess=false)
4  public class MyWebService implements IMyWebService {

6    @WebMethod
7    @NotNull
8    public ArrayList<SearchResult> performSearch(ArrayList<String> criteria) {
9      GetAllResponses caller = new GetAllResponses();
10     return caller.doSearch(criteria);
11   }

13 }

Класс GetAllResponses выглядит следующим образом:

1  public class GetAllResponses {
2    private static MyHome myHome = new MyHome();

4    public SearchResult doSearch(ArrayList<String> criteria) {
5      return doSearchInternal(criteria.elementAt(0), criteria.elementAt(1));
6    }

8    private SearchResult doSearchInternal(String a, String b) {
9      DataObject info = myHome.findDataObject(a, b);
10     return info.getAsSearchResult();
11   }
12 }

А MyHome выглядит следующим образом:

1  @Stateless
2  @Local({MyHomeInterface.class})
3  public class MyHome {
4    private Session session;

6    public DataObject findDataObject(String a, String b) {
7        try {
8            this.session = MyHibernateUtil.getSessionFactory().getCurrentSession();
9            Transaction tx = this.session.beginTransaction();
10           //do stuff with session and return a DataObject
11       } catch (Exception ex) {
12           ex.printStackTrace();
13       } finally {
14           this.session.close();
15       }
16   }

18   public DataObject doAnotherFind(String a, String b) {
19       try {
20           this.session = MyHibernateUtil.getSessionFactory().getCurrentSession();
21           Transaction tx = this.session.beginTransaction();
22           //do stuff with session and return a DataObject
23       } catch (Exception ex) {
24           ex.printStackTrace();
25       } finally {
26           this.session.close();
27       }
28  }

30 }

Обратите внимание, как во второй строке GetAllResponses класс MyHome создается как статическое поле, а в строках 8 и 20 MyHome назначено поле session.

Исходя из моего понимания вещей, SSB MyHome не управляется сервером J2EE (JBoss 4.2.2 GA), поскольку он был создан как статическое поле класса GetAllResponses, а не обращен к нему JNDI. Следовательно, два потока могут обращаться к одному и тому же экземпляру MyHome в одно и то же время, и поскольку сеанс хранится в поле session, первый вызов может очень легко заменить его Session другим Session, что приведет к всевозможные проблемы, включая org.hibernate.SessionException: Session is closed! в строках 9 и 21 из MyHome (например, два потока вызывают findDataObject, первый поток запускает строку 14 сразу после того, как второй поток запускает строку 8 и до того, как он запускает строку 9).

Я прав?

1 Ответ

2 голосов
/ 10 марта 2011

Да, вы правы.

Также имейте в виду, что даже если myHome не был статичным, все объекты, возвращаемые MyHome, были бы отключены от сеанса.Вы не сможете инициализировать ленивые свойства извне MyHome.

Переменная сеанса также должна быть локальной переменной в методах MyHome, а не переменной экземпляра.

Но основная проблема заключается в том, что сессионные компоненты без сохранения состояния должны использоваться для декларативного разграничения транзакций.В среде EJB вам не нужно открывать, фиксировать и откатывать транзакции, а также закрывать сеансы.Все должно быть сделано с помощью синхронизации транзакций JTA, реализованной с помощью sessionFactory.getCurrentSession ().

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