1、关于SessionFactory和Session
SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一 个SessionFactory并从中获取Session实例,而Session不是线程安全的。Session中包含了数 据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,就很有可能导致数据存取的混乱。每个线程/事务应该从一个SessionFactory获取自己的session实例,才能在新线程中使用事务和延迟加载等功能,否则会曝出no session异常。
- new Runnable() {
- @Override
- public void run() {
- // ----------绑定session到当前线程------------
- SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
- boolean participate = ConcurrentUtil.bindHibernateSessionToThread(sessionFactory);
- // ---------你的业务---------------
- <pre name="code" class="java">// ----------关闭session------------
- ConcurrentUtil.closeHibernateSessionFromThread(participate, sessionFactory);
- }
- }
其中applicationContext.getBean("xxx"),可能涉及到多线程的spring注解注入问题
- public static boolean bindHibernateSessionToThread(SessionFactory sessionFactory) {
- if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
- // Do not modify the Session: just set the participate flag.
- return true;
- } else {
- Session session = sessionFactory.openSession();
- session.setFlushMode(FlushMode.MANUAL);
- SessionHolder sessionHolder = new SessionHolder(session);
- TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
- }
- return false;
- }
- public static void closeHibernateSessionFromThread(boolean participate, Object sessionFactory) {
- if (!participate) {
- SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
- SessionFactoryUtils.closeSession(sessionHolder.getSession());
- }
- }
事务边界则由aop或者Transactional标记来控制,示例代码只是保证具备事务性的方法在需要的时候能从当前线程中获得session对象。
上述代码大部分截取自Spring的OpenSessionInViewFilter。
2、session的创建:
Hibernate中的Session通过SessionFactory来创建,具体的创建方式有两种:
SessionFactory.getCurrentSession()、SessionFactory.openSession() ;
这两种创建Session的方式主要有如下差别:
a:getCurrentSession创建的session会绑定到当前线程,而openSession不会。
b:getCurrentSession创建的线程会再事务回滚或事务提交后自动关闭,而openSession必须手动关闭
c:getCurrentsession需要在hibernate.cfg.xml文件中添加配置: <propertyname="current_session_context_class">thread</property>
3、spring hibernate session
使用hibernate进行数据库操作时,需要session,并且需要对sesssion进行事务管理.
当使用spring来集成hibernate时,spring会帮我们管理session的事务,因此无需我们手动操作事务(提交、回滚等)。
在Spring托管中,session并不是程序员自己控制的,session的生命周期交由Spring管理。影响session生命周期的情况有这几种:
使用SessionFactory.getCurrentSession()方法。
使用HibernateTemplate来屏蔽对session的直接访问。
使用HibernateTransactionManager,并在session使用区域外围包装了本地事务,甚至是事务嵌套。
使用了JtaTransactionManager,并在session使用区域外围包装了Jta事务,甚至是事务嵌套。
使用了OpenSessionInViewFilter。