|
|
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
Допустим, что в hibernate-приложении требуется выполнить некий sql-запрос напрямую. Решил посмотреть, что будет при одновременной работе несколькими потоками. hibernate.properties Код: plaintext 1. 2. 3. 4. 5. 6. 7. Timeout.java (взят у Эккеля из "Философии") Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 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. Чего смущает: в обоих потоках сессия одна и та же, один из результатов выполнения: Код: 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. Как в таком случае реализуется пул коннектов? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 18:57 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
Сессия - это НЕ 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 поработать с ней, а затем закрыть (вернуть в пул) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 19:26 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
Denis PopovЧего смущает: в обоих потоках сессия одна и та же, один из результатов выполнения: Любопытно, а что вы ожидали?... Оба потока используют одну и ту же сессию, а следовательно, одно и то же соединение. Для того, чтобы каждый поток использовал свою сессию и свое соединение (а это обязательно), следует либо а) в каждом потоке брать сессию (и не забывать ее закрывать по окончании работы), либо б) создать и использовать пул сессий. Я обычно использую более эффективный промежуточный вариант - создаю пул классов - исполнителей, которые реализуют бизнес-функции и обслуживают запросы приложений. Каждый исполнитель при активации берет сессию, а при пассивации закрывает ее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 19:48 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
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 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 19:53 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
М.Голованов wrote: > Любопытно, а что вы ожидали?... Оба потока используют одну и ту же > сессию, а следовательно, одно и то же соединение . Да, вот это я и прояснил для себя. Главное другое: после вызова session.disconnect() коннект к базе не уничтожается, а возвращается в пул коннектов и м.б. отдан другой вновь открытой сессии. и если при работе напрямую с JDBC и я прошу каждый раз e пула коннектов дать мне Connection, то тут у SessionFactory я прошу дать мне Session. Posted via ActualForum NNTP Server 1.3 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 19:57 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
Denis PopovТогда вопрос, может наивный: при работе с Hibernate требуется ли каждый раз получать новую Session из SessionFactory для некоей бизнес-операции (например, сохранить документ), либо все пользователи работают с одним экземпляром Session? Хороший вопрос. Ответ будет такой. У Вас запрос приложения может быть такой, что надо выполнить несколько операций. Ну, например, сохранить документ, потом создать запись в каком-нибудь реестре операций, потом еще что-нибудь... НО выполнение этого запроса (происходящее в одном потоке - например, в запросе, который исполняется Веб-приложением) требует получения новой сессии, выполнения всех операций и закрытия ее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 20:19 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
Denis Popovи если при работе напрямую с JDBC и я прошу каждый раз e пула коннектов дать мне Connection, то тут у SessionFactory я прошу дать мне Session YES!!! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 20:21 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
требуется ли каждый раз получать новую Session из SessionFactory для некоей бизнес-операции (например, сохранить документ), либо все пользователи работают с одним экземпляром Session? Это зависит от стратегии работы. Есть приложения которые хранят активной сессию и соединение с БД все время работы (обычно если число клиентов колеблется в заранее известных рамках), есть те кто ориентируются на пул (веб приложения) Насчет же сессии hibernate'а - тут важно помнить 3 вещи - во-первых, пул организуется для "дорогих" и/или ограниченных ресурсов. Для чего-то легкого он не нужен - во-вторых, сама сессия hibernate'а - это легкий объект, НО она использует соединение с БД, которое является классическим кандидатом для poolable object. - обычно от пула соединений с БД противопоказаний нет. Настраивается он легко, концепция и задачи у него ясные. Таким образом, пул jdbc соединений создавать стоит, пул для сессий hibernate'а - нет и создавать их стоит динамически по необходимости - так как при работающем пуле соединений с БД эта операция будет дешевой ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.11.2005, 23:51 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
Ок, спасибо. Еще один вопрос, или ткните носом в пункт документации: существует ли нечно вроде "кеша объектов", т.е. всегда ли данные по запросу берутся из базы, или не всегда? Я к тому что не получится ли ситуация, когда выполненный напрямую (через Connection) запрос к БД, изменивший данные в ней, приводит в несоответствие этот самый кеш с реальным состоянием БД, но Hibernate об этом не подозревает? Posted via ActualForum NNTP Server 1.3 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.11.2005, 20:26 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
существует ли нечно вроде "кеша объектов", т.е. всегда ли данные по запросу берутся из базы, или не всегда Очень интересный вопрос на самом деле... Кэширование - очень важная составляющая большинства крупных систем, связанных с обработкой данный. Это большая тема, конкретно для 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.11.2005, 22:27 |
|
||
|
Hibernate и Session.connection()
|
|||
|---|---|---|---|
|
#18+
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). Таким образом, все в общем просто. Надо просто внимательно кодировать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.11.2005, 10:43 |
|
||
|
|

start [/forum/topic.php?fid=59&fpage=768&tid=2150927]: |
0ms |
get settings: |
6ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
47ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
42ms |
get tp. blocked users: |
2ms |
| others: | 219ms |
| total: | 345ms |

| 0 / 0 |
