当 Spring4 和 Hibernate4 整合后,事务不起作用
解决办法:通过Spring的SessionFactory的getCurrentSession的方法创建Session
一、首先说一下hibernate中创建用来连接数据库的Session,有两种方式。
- 通过Spring的SessionFactory的getCurrentSession的方法创建Session 。
- 通过Spring的SessionFactory的OpenSession的方法创建Session。
getCurrentSession 创建的Session会绑定到当前线程中去,commit或rollback后会,自动关闭Session。
OpenSession 重新开启一个线程创建Session,需要手动关闭Session,如果不关闭将导致session关联的数据库连接无法释放,最后资源耗尽而使程序当掉。
二、而当Hibernate利用Spring中的绑定事务来配置的时候如下图:
<context:component-scan base-package=""/>
<context:component-scan base-package=""/>
<!--1.配置数据源-->
<!--1.1导入资源文件-->
<context:property-placeholder location="classpath:"/>
<bean class=".v2.">
<property name="user" value="${}"/>
<property name="password" value="${}"/>
<property name="driverClass" value="${}"/>
<property name="jdbcUrl" value="${}"/>
<property name="initialPoolSize" value="${}"/>
<property name="maxPoolSize" value="${}"/>
</bean>
<!--2.配置Hibernate的SessionFactory 实例:通过Spring提供的:LocalSessionFactoryBean进行配置-->
<bean class=".">
<!--2.1配置数据源属性-->
<property name="dataSource" ref="comboPooledDataSource"/>
<!--2.2配置hibernate配置文件的位置及名称-->
<property name="configLocation" value="classpath:"/>
<!--2.3配置hibernate映射文件的位置及名称,可以使用通配符-->
<property name="mappingResources">
<list>
<value></value>
<value></value>
</list>
</property>
</bean>
<!--3.配置Spring声明式事务-->
<!--3.1配置事务管理器-->
<bean class=".">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!--3.2配置事务属性,需要事务管理器-->
<tx:advice transaction-manager="hibernateTransactionManager" >
<tx:attributes>
<!--<tx:method name="purchase" propagation="REQUIRED"/>-->
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!--3.3配置事务切点,并把切点和事务属性关联起来-->
<aop:config>
<aop:pointcut expression="execution(* .*.*(..))"/>
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="txPointcut"/>
</aop:config>
配置事务是,需要将数据库中的数据源,注入 HibernateTransactionManager可以说,事务的配置是,针对于数据库来说的。(我是这么理解的)
所以,当我们采用OpenSession来创建Session来连接数据库的话,和事务连接数据库是两个线程的操作,所以事务根本不会起作用。
应该采用getCurrentSession进行session的创建。