powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate и Session.connection()
12 сообщений из 12, страница 1 из 1
Hibernate и Session.connection()
    #33387722
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Допустим, что в hibernate-приложении требуется выполнить некий sql-запрос напрямую. Решил посмотреть, что будет при одновременной работе несколькими потоками.

hibernate.properties
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.connection.driver_class=oracle.jdbc.OracleDriver

#hibernate.connection.pool_size= 3 

hibernate.c3p0.minPoolSize= 3 
hibernate.c3p0.maxPoolSize= 10 

Timeout.java (взят у Эккеля из "Философии")
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
 import  java.util.Timer;
 import  java.util.TimerTask;

 public   class  Timeout
   extends  Timer {

   public  Timeout( int  delay,  final  String msg) {
     super (true); // Daemon thread
    schedule(
       new  TimerTask() {
         public   void  run() {
          System.out.println(msg);
          System.exit( 0 );
        }
      }, delay
    );
  }
}

TestHibernatePool.java
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
 import  org.hibernate.Session;
 import  org.hibernate.SessionFactory;
 import  org.hibernate.cfg.Configuration;

 import  java.sql.Connection;
 import  java.sql.ResultSet;
 import  java.sql.SQLException;
 import  java.sql.Statement;

 public   class  TestHibernatePool {

   public   static  Session session;

   public   static   void  main(String[] args)
     throws  Exception {

    SessionFactory sessionFactory =  new  Configuration().configure().buildSessionFactory();
    session = sessionFactory.openSession();

     new  SQL("A",  5 ).start();
     new  SQL("B",  5 ).start();
     new  Timeout( 1000 , "Terminated");

  }

}

 class  SQL
   extends  Thread {

   private  String name;

   private   int  counter =  10 ;

   public  SQL(String name,  int  counter) {
     this .name = name;
     this .counter = counter;
  }

   public   void  run() {
     for  ( int  i =  0 ; i < counter; i++) {
      Connection con = TestHibernatePool.session.connection();
      System.out.println(name + " : " + con);
      Statement st =  null ;
      ResultSet rs =  null ;
       try  {
        st = con.createStatement();
        rs = st.executeQuery("select sys_context('userenv', 'sessionid') audsid from dual");
         if  (rs.next()) {
          System.out.println(name + " : " + rs.getString("audsid"));
        }
      }  catch  (SQLException e) {
        System.out.println("SQLException\n" + e.toString());
      }  finally  {
         if  (rs !=  null ) { try  {rs.close();}  catch  (SQLException e) {}}
         if  (st !=  null ) { try  {st.close();}  catch  (SQLException e) {}}
//        if (con != null) {con.close();}
      }
    }
  }
}

Чего смущает: в обоих потоках сессия одна и та же, один из результатов выполнения:


Как в таком случае реализуется пул коннектов?
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33387767
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сессия - это НЕ threadsafe объект и ее можно использовать только в одном потоке...
hibernate
A SessionFactory is threadsafe, many threads can access it concurrently and request Sessions. A Session is a non-threadsafe object that represents a single unit-of-work with the database. Sessions are opened from a SessionFactory and are closed when all work is completed. An example in your servlet's process() method might look like this (sans exception handling):

Таким образом в вашем классе TestHibernatePool переменную session нужно объявлять как ThreadLocal

См.
http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html#configuration-sessionfactory

Как в таком случае реализуется пул коннектов?

С SessionFactory связан DataSource, который и реализует пул соединений. Для выполнения unit of work нужно получить сессию из SessionFactory поработать с ней, а затем закрыть (вернуть в пул)
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33387793
М.Голованов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis PopovЧего смущает: в обоих потоках сессия одна и та же, один из результатов выполнения:

Любопытно, а что вы ожидали?... Оба потока используют одну и ту же сессию, а следовательно, одно и то же соединение.

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

Я обычно использую более эффективный промежуточный вариант - создаю пул классов - исполнителей, которые реализуют бизнес-функции и обслуживают запросы приложений. Каждый исполнитель при активации берет сессию, а при пассивации закрывает ее.
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33387797
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
funikovyuri wrote:

> С SessionFactory связан DataSource, который и реализует пул соединений.
> Для выполнения unit of work нужно получить сессию из SessionFactory
> поработать с ней, а затем закрыть (вернуть в пул)

Понял, т.е. получаешь Session через SessionFactory.openSession(), в ней есть Connection, после
работы вызываешь session.disconnect()? Тогда вопрос, может наивный: при работе с Hibernate требуется
ли каждый раз получать новую Session из SessionFactory для некоей бизнес-операции (например,
сохранить документ), либо все пользователи работают с одним экземпляром Session?
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33387801
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
М.Голованов wrote:
> Любопытно, а что вы ожидали?... Оба потока используют одну и ту же
> сессию, а следовательно, одно и то же соединение .

Да, вот это я и прояснил для себя. Главное другое: после вызова session.disconnect() коннект к базе
не уничтожается, а возвращается в пул коннектов и м.б. отдан другой вновь открытой сессии. и если
при работе напрямую с JDBC и я прошу каждый раз e пула коннектов дать мне Connection, то тут у
SessionFactory я прошу дать мне Session.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33387841
М.Голованов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis PopovТогда вопрос, может наивный: при работе с Hibernate требуется ли каждый раз получать новую Session из SessionFactory для некоей бизнес-операции (например, сохранить документ), либо все пользователи работают с одним экземпляром Session?

Хороший вопрос. Ответ будет такой. У Вас запрос приложения может быть такой, что надо выполнить несколько операций. Ну, например, сохранить документ, потом создать запись в каком-нибудь реестре операций, потом еще что-нибудь...

НО выполнение этого запроса (происходящее в одном потоке - например, в запросе, который исполняется Веб-приложением) требует получения новой сессии, выполнения всех операций и закрытия ее.
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33387845
М.Голованов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis Popovи если
при работе напрямую с JDBC и я прошу каждый раз e пула коннектов дать мне Connection, то тут у SessionFactory я прошу дать мне Session

YES!!!
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33388020
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
требуется
ли каждый раз получать новую Session из SessionFactory для некоей бизнес-операции (например,
сохранить документ), либо все пользователи работают с одним экземпляром Session?

Это зависит от стратегии работы. Есть приложения которые хранят активной сессию и соединение с БД все время работы (обычно если число клиентов колеблется в заранее известных рамках), есть те кто ориентируются на пул (веб приложения)

Насчет же сессии hibernate'а - тут важно помнить 3 вещи
- во-первых, пул организуется для "дорогих" и/или ограниченных ресурсов. Для чего-то легкого он не нужен
- во-вторых, сама сессия hibernate'а - это легкий объект, НО она использует соединение с БД, которое является классическим кандидатом для poolable object.
- обычно от пула соединений с БД противопоказаний нет. Настраивается он легко, концепция и задачи у него ясные.

Таким образом, пул jdbc соединений создавать стоит, пул для сессий hibernate'а - нет и создавать их стоит динамически по необходимости - так как при работающем пуле соединений с БД эта операция будет дешевой
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33388489
Фотография Denis Popov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ок, спасибо. Еще один вопрос, или ткните носом в пункт документации: существует ли нечно вроде "кеша объектов", т.е.
всегда ли данные по запросу берутся из базы, или не всегда? Я к тому что не получится ли ситуация, когда выполненный
напрямую (через Connection) запрос к БД, изменивший данные в ней, приводит в несоответствие этот самый кеш с реальным
состоянием БД, но Hibernate об этом не подозревает?
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33388548
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
существует ли нечно вроде "кеша объектов", т.е.
всегда ли данные по запросу берутся из базы, или не всегда

Очень интересный вопрос на самом деле... Кэширование - очень важная составляющая большинства крупных систем, связанных с обработкой данный. Это большая тема, конкретно для hibernate'а, картину проясняет это:

The Second Level Cache

A Hibernate Session is a transaction-level cache of persistent data. It is possible to configure a cluster or JVM-level (SessionFactory-level) cache on a class-by-class and collection-by-collection basis. You may even plug in a clustered cache. Be careful. Caches are never aware of changes made to the persistent store by another application (though they may be configured to regularly expire cached data).

Обратите внимание на последнее предложение. Для кэшей вобще есть такое понятие как актуальность данных. Так, например, в пределе если данные меняет только одно приложение - их все можно поместить в кэш уровня JVM, и они будут вечно актуальны, и наоборот, если одни и теже данные меняются различными приложениями независимо, то смысла в кэше может уже и не быть.

Так что тут 2 аспекта
- согласованность (т.е. влияние на обеспечение Transaction Isolation). Кэши на нее не влияют, так как она как организуется либо с помощью optimistic locking либо с помощью pessimistic locking. Для первой в случае использования неактуальных данных из кеша это будет выяснено в момент commit'a, для второй никто не сможет получить к этим данным доступ, пока работа с ними не будет завершена
- эффективная работа. Тут можно посоветовать окуратно писать код, используя где надо session.flush(), session.evict(), Query.setCacheable(). Грамотно настраивать кэш и следить за его статистикой.

Подробнее см. http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache%5D20.2.]http://www.hibernate.org/hib_docs/v3/reference/en/html/performance.html#performance-cache]20.2.
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33388645
М.Голованов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Denis Popov
Ок, спасибо. Еще один вопрос, или ткните носом в пункт документации: существует ли нечно вроде "кеша объектов", т.е.
всегда ли данные по запросу берутся из базы, или не всегда? Я к тому что не получится ли ситуация, когда выполненный
напрямую (через Connection) запрос к БД, изменивший данные в ней, приводит в несоответствие этот самый кеш с реальным
состоянием БД, но Hibernate об этом не подозревает?

1. Пункт 14.4. Managing the Session Cache в Hibernate Reference Documentation.

2. Такая ситуация запросто получится, если вы загрузите некий объект в сессии и оставите его в Session cache (то есть не сделаете evict с этим объектом или не очистите сессию методом clear. Если вы после загрузки этого объекта прямым SQL измените его атрибуты (поля таблицы в БД), эти изменения НЕ БУДУТ отражены в кэшированном объекте. Более того, повторный load этого объекта будет выполнен из кэша, и опять-таки изменения не будут отражены в его атрибутах.

Так что если вы хотите изменить атрибуты кэшированного объекта прямым SQL, перед или после вызова SQL следует "убить" объект в кэше сессии, методом evict (только данный объект) или clear (все кэшированные объекты). Если с таким объектом надо работать далее в этой сессии, его следует снова загрузить (load).

Таким образом, все в общем просто. Надо просто внимательно кодировать.
...
Рейтинг: 0 / 0
Hibernate и Session.connection()
    #33388680
funikovyuri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В последнем моем посте авторс помощью optimistic locking
следует читать как авторс помощью optimistic locking with versioning
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate и Session.connection()
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]