Hibernate中获取两种Session实例的方法
在hibernate中有两种方法获得session
1.openSession()
2.getCurrentSession()
两种方法的区别
1.openSession()每次创建新的session对象,getCurrentSession()使用现有的session对象 (类似单例模式)
2.getCurrentSession在事务提交或者回滚之后会自动关闭,而openSession()需要手动关闭(session.close()),如果使用openSession()后未关闭,多次创建后会导致线程池溢出。
如果使用的getCurrentSession()方法 就要在hibernate.cfg.xml文件中进行配置,Hibernate4.0以后可以采用spring配置文件
加@Trancation注解的形式获取当前的session实例,例
<!-- 5.事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--6.事务-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
由于在项目中引用了Java Socket,所以开启多线程去解析socket客户端的数据,突然发现一个坑爹的问题,当同时开启20个线程去解析数据的时候,会发生整个服务的线程阻塞和MySQL进程sleep
定位线程阻塞问题
show processlist发现如图所示,
许多mysql进程sleep,我kill掉所有正在运行的进程,然后
set global wait_timeout=300;
set global interactive_timeout=300;
重启服务以后,当线程开启到50个的时候发现又有大量的进程sleep
我开始定位程序中的问题,我查询用的是getCurrentSession,但解析客户端socket数据用的openSession
/**
*getCurrentSession
* 获取新的session
* @return
*/
public Session findSession() {
return sessionFactory.getCurrentSession();
}
/**
*openSession
*
*/
//创建会话工厂
SessionFactory sessionFactory=(SessionFactory)
SpringContext.getBean("sessionFactory");
//创建会话session
Session session=sessionFactory.openSession();
//开启会话事务
Transaction transaction=session.beginTransaction();
之前使用getCurrentSession的时候都是使用@trancation注解自动提交事务和关闭session,但opneSession需要手动关闭,
这里由于没有手动关闭,造成A事务和B事务同时对Table表操作,导致数据库死锁,当我在每次执行完数据解析以后加上
session.flush();
session.close();
重启服务跑一下,再没遇到线程阻塞的情况(想拍死自己),但访问主线程查询的时候发现又遇到问题,如图
我在配置文件中加了
> <prop key="hibernate.current_session_context_class">thread</prop>
Spring和Hibernate整合事务配置之current_session_context_class
hibernate.current_session_context_class设置原来配置事务模式:
<prop key="hibernate.current_session_context_class">thread</prop>
会出现不存在激活的事务现象,主要原因是由于咋Spring管理事务中currentsession是绑定下springsessioncontext中的,而不是绑定在threadlocalsessioncontext中的。
hibernate.current_session_context_class常用3种配置:
jta,thread,org.springframework.orm.hibernate4.SpringSessionContext
hibernate.current_session_context_class=thread
实质是: hibernate.current_session_context_class=
org.hibernate.context.internal.ThreadLocalSessionContext
org.hibernate.context.internal.ThreadLocalSessionContext -
当前session通过当前执行的线程来跟踪和界定。
hibernate.current_session_context_class=jta
实质是: hibernate.current_session_context_class=
org.hibernate.context.internal.JTASessionContext
org.hibernate.context.internal.JTASessionContext-
当前session根据JTA来跟踪和界定。这和以前的仅支持JTA的方法是完全一样的。
hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
实质是 Spring @Transactional声明式事务管理,”currentSession”的定义为: 当前被 Spring事务管理器
管理的Session,此时应配置:
hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
spring 整合hibernate管理事务后,由Spring的TransactionManager管理事务后, currentSession是绑定到SpringSessionContext的,而不是thread。
此时hibernate.current_session_context_class应该是SpringSessionContext,而它又会在使用LocalSessionFactoryBean时自动的设置。
所以就不需要你去设置current_session_context_class