1、关于SessionFactory和Session
SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一 个SessionFactory并从中获取Session实例,而Session不是线程安全的。Session中包含了数 据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,就很有可能导致数据存取的混乱。
2、session的创建:
Hibernate中的Session通过SessionFactory来创建,具体的创建方式有两种:SessionFactory.getCurrentSession()、SessionFactory.openSession();
这两种创建Session的方式主要有如下差别:
- getCurrentSession创建的session会绑定到当前线程,而openSession不会。
- getCurrentSession创建的线程会再事务回滚或事务提交后自动关闭,而openSession必须手动关闭
- getCurrentsession需要在hibernate.cfg.xml文件中添加配置:
<propertyname="current_session_context_class">thread</property>
3、current_session_context_class类型
这个参数设置hibernate管理session的方式(session的范围)。hibernate共有三种方式并且都对应三个实现类实现接口org.hibernate.context.spi.CurrentSessionContext:
a、thread(org.hibernate.context.ThreadLocalSessionContext):当前session通过当前执行的线程来跟踪和界定。
这样配置是本地jdbc事物配置,通过getCurrentSession创建session绑定到当前线程。
这种方式创建的session中并没有获得transaction,我们都要手动调用session.beginTransaction()来打开一个活动的事物。
b、jta(org.hibernate.context.internal.JTASessionContext):当前session根据JTA来跟踪和界定
c、manager(org.hibernate.context.internal.ManagerdSessionContext)
4、Spring实现的current_session_context_class类型
tspring整合hibernate后,由spring的TransactionManager管理hibernate的事务,currentSession是绑定到SpringSessionContext的,而不是thread,此时current_session_context_class的设置应该是spring对CurrentContextSession接口的实现类:SpringSessionContext。
a、@Transactional声明的方法执行时,Spring的TransactionManager会自动Open Session,自动开启事务,并且 将此Session绑定到SpringSessionContext(实际上是TransactionSynchronizationManager的Threadlocal的Map中)
b、SessionFactory.getCurrentSession()方法执行时,调用SpringSessionContext.currentSession()从TransactionSynchronizationManager的上下文中查找当前session
c、找到后返回当前Session,找不到返回HibernateException(“No Sessionfound for current thread”) ;
5、总结
使用hibernate进行数据库操作时,需要session,并且需要对sesssion进行事务管理。hibernate有三种类型,界定了session的作用域。当使用spring来集成hibernate时,spring会帮我们管理session的事务,因此无需我们手动操作事务(提交、回滚等)。
当然在使用session的时候,注意session的范围,当出现no session异常的情况时,查看配置文件,弄清楚设置session界定的范围,然后定位问题找到解决方案。