Контролировать сеанс гибернации (когда закрывать его вручную) - PullRequest
63 голосов
/ 28 октября 2010

Я новичок в hibernate, после прочтения api и учебника hibernate кажется, что сессия должна закрываться, когда она не используется.

Как это:

Session sess=getSession();
Transcration tx=sess.beginTranscration();
//do something using teh session
sess.save(obj);
tx.commit();
sess.close;

У меня нет вопросов при использовании его в автономном приложении. Однако я не уверен при использовании в веб-приложении.

Например, у меня есть сервлет: TestServlet для получения параметров от клиента, затем я вызываю менеджера для запроса чего-либо в соответствии с параметрами, например:

class TestServlet{
  doGet(HttpServletRequset,httpServletResponse){
    String para1=request.getParam...();
    String para2=.....
    new Manager().query(para1,para2);
  }
}

class Manager{
  public String query(String pa1,String pa2){
    Session=....// get the session
    //do query using para1 and 1
    session.close() //Here, I wonder if I should close it.
  }
}

Должен ли я закрыть сеанс в методе запроса?

Так как кто-то сказал мне, что сессия в hibernate такая же, как соединение в jdbc. Так что открывать и закрывать его так часто - правильный путь?

Кстати, требуется ли tx.commit () каждый раз?

Кроме того, в чем проблема с использованием сеанса в сервлете, поскольку я видел, что сеанс не является потокобезопасным в API.

Ответы [ 4 ]

113 голосов
/ 29 октября 2010

Я новичок в hibernate, после прочтения api и учебника hibernate кажется, что сессия должна закрыться, когда она не используется.

Она должна быть закрыта, когда вы закончите с(но это может быть сделано автоматически для вас, как мы увидим).

У меня нет вопросов при использовании его в автономном приложении.Однако я не уверен при использовании в веб-приложении.

Ну, как объяснено в разделе 11.1.1.Единица работы документации, наиболее распространенный шаблон в многопользовательском клиент-серверном приложении - сеанс на запрос .

Например, у меня есть сервлет: TestServlet для получения параметров от клиента, затем я вызываю менеджера для запроса чего-либо в соответствии с параметрами: просто так (...) Должен ли я закрыть сессиюв методе запроса?

Все зависит от того, как вы получаете сеанс.

  • Если вы используете sessionFactory.getCurrentSession(), вы получите «текущий сеанс», которыйпривязан к жизненному циклу транзакции и будет автоматически очищаться и закрываться по завершении транзакции (фиксация или откат).
  • Если вы решите использовать sessionFactory.openSession(), вам придется самостоятельно управлять сеансом исбросить и закрыть его «вручную».

Чтобы реализовать шаблон сеанс на запрос , предпочтите первый подход (гораздо более простой и менее многословный).Используйте второй подход для реализации длинных разговоров .

Вики-страница Сеансы и транзакции является хорошим дополнением к документации по этой теме.

Кстати, требуется ли tx.commit () каждыйвремя?

Возможно, вы захотите прочитать Нетранзакционный доступ к данным и режим автоматической фиксации , чтобы уточнить некоторые моменты, но, проще говоря, ваш код Hibernate долженбыть выполненным в транзакции, и я бы предложил использовать явные границы транзакции (то есть явные beginTransaction и commit).

Кроме того, в чем проблема с использованием сеанса в сервлете, поскольку я виделсеанс не является поточно-ориентированным в API.

Просто не делайте его переменной-переменной сервлета, и у вас не возникнет никаких проблем.

Ссылки

0 голосов
/ 08 июля 2019

Сессия открывается всякий раз, когда getCurrentSession() вызывается впервые, и закрывается, когда транзакция заканчивается.

Это создает новый сеанс, если он не существует, или использует существующий, если он уже существует. Он автоматически настраивается с использованием атрибутов auto-flush и auto-close, поскольку значение true означает, что Session будет автоматически очищено и закрыто.

Если вы используете getCurrentSession(), то нет необходимости закрывать соединение, если вы попробуете это, тогда вы столкнетесь с исключением.

0 голосов
/ 04 июля 2016

Мы можем использовать ThreadLocal.

public class MyUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal;

static {
try {
    Configuration configuration = new Configuration();
    configuration.configure();
    serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    threadLocal = new ThreadLocal<Session>();

    } catch(Throwable t){
      t.printStackTrace();
      throw new ExceptionInInitializerError(t);
    }
}
public static Session getSession() {
    Session session = threadLocal.get();
    if(session == null){
        session = sessionFactory.openSession();
        threadLocal.set(session);
    }
    return session;
}

public static void closeSession() {
    Session session = threadLocal.get();
    if(session != null){
    session.close();
    threadLocal.set(null);
    }
}

public static void closeSessionFactory() {
    sessionFactory.close();
    StandardServiceRegistryBuilder.destroy(serviceRegistry);
   }
}

Здесь SessionFactory инициализируется только один раз с использованием статического блока. Следовательно, всякий раз, когда класс main вызывает getSession(), наличие объекта Session сначала проверяется в объекте threadLocal. Следовательно, эта программа обеспечивает безопасность потоков. После каждой операции closeSession() закрывает сеанс и устанавливает для объекта threadLocal значение null. Наконец позвоните closeSessionFactory().

0 голосов
/ 21 марта 2016

Если вы получаете сеанс через sessionFactory.openSession(), тогда вам нужно закрыть его снаружи .Открытый сеанс на непредвиденный период может привести к утечке данных.Кроме того, он может дать приглашение угрозе безопасности веб-приложения.

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