Управление сеансом спящего режима (когда его закрыть вручную)
Я новичок в спящем режиме, после чтения hibernate api и учебника, кажется, что сеанс должен закрываться, когда он не используется.
Вот так:
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.
}
}
Должен ли я закрывать сеанс в методе запроса?
Так как кто-то сказал мне, что сеанс в спящем режиме похож на соединение в jdbc. Так что открытие и закрытие так часто является правильным способом?
Кстати, требуется ли tx.commit() каждый раз?
Также проблема с потоком об использовании сеанса в сервлетах, так как я видел, что сеанс не является потокобезопасным в api.
Ответы
Ответ 1
Я новичок в спящем режиме, после чтения hibernate api и учебника, кажется, что сессия должна быть закрыта, если не используется.
Он должен быть закрыт, когда вы закончите (но это может быть сделано автоматически для вас, как мы увидим).
У меня нет вопросов при использовании в автономном приложении. Однако я не уверен при использовании в веб-приложении.
Ну, как объясняется в разделе 11.1.1. Единица работы документации, наиболее распространенный шаблон в многопользовательском клиент-серверном приложении сеанс за запрос.
Например, у меня есть сервлет: TestServlet для получения параметров от клиента, затем я вызываю диспетчера для запроса чего-либо в соответствии с параметрами: точно так же (...) Должен ли я закрывать сеанс в методе запроса
Все зависит от того, как вы получаете сеанс.
- если вы используете
sessionFactory.getCurrentSession()
, вы получите "текущий сеанс", привязанный к жизненному циклу транзакции, и он будет автоматически очищен и закрыт при завершении транзакции (фиксация или откат).
- если вы решите использовать
sessionFactory.openSession()
, вам придется самостоятельно управлять сеансом и скрывать его вручную.
Чтобы реализовать шаблон сеанса за запрос, предпочитайте первый подход (гораздо проще и менее подробным). Используйте второй подход для выполнения длинных цепочек .
Страница wiki Сессии и транзакции является хорошим дополнением к документации по этой теме.
Кстати, требуется ли tx.commit() каждый раз?
Возможно, вы захотите прочитать Доступ к транзакционным данным и режим автоматической фиксации, чтобы прояснить несколько вещей, но, проще говоря, ваш Hibernate-код должен быть выполнен внутри транзакции, и я предлагаю использовать явные границы транзакций (т.е. явные beginTransaction
и commit
).
Также проблема с потоком об использовании сеанса в сервлетах, так как я видел, что сеанс не является потокобезопасным в api.
Просто не делайте его переменной экземпляра сервлета, и у вас не будет проблем.
Ссылки
- Справочное руководство по Hibernate Core 3.3
- Hibernate wiki
Ответ 2
Если вы проходите сессию через sessionFactory.openSession()
, вам нужно закрыть ее снаружи. Открытая сессия в течение непредвиденного периода может привести к утечке данных. Кроме того, он может дать приглашение угрозе безопасности веб-приложений.
Ответ 3
Мы можем использовать 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()
.
Ответ 4
Сессия открывается всякий раз, когда getCurrentSession()
вызывается впервые, и закрывается, когда транзакция заканчивается.
Это создает новый сеанс, если он не существует, или использует существующий, если он уже существует. Он автоматически настраивается с использованием атрибутов auto-flush и auto-close, поскольку значение true означает, что Session
будет автоматически очищена и закрыта.
Если вы используете getCurrentSession()
то нет необходимости закрывать соединение, если вы собираетесь попробовать это, тогда вы столкнетесь с исключением.