集成的好处
- 由IOC容器来管理Hibernate的SessionFactory
- 让Hibernate使用上Spring的声明式事务(就不用手动的开启,关闭事务了)
过程讲解
1.Hibernate对应的DAO层继承HibernateDaoSupport类,这个类属于Spring框架的,是Spring对Hibernate的集成,该类需要使用Spring向其注入sessionFactory,DAO层代码,继承HibernateDaoSupport
public class UserManagerImpl extends HibernateDaoSupport implements UserManager {
@Override
public void addUser(User user) {
this.getHibernateTemplate().save(user);
}
}
HibernateDaoSupport 的一个方法是 getHibernateTemplate:
public final HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
2.在Hibernate的配置文件中声明事务是本地事务:
<!-- 存放在threadlocal中 -->
<property name="hibernate.current_session_context_class">thread</property>
3.配置Spring,首先将DAO交给Spring管理,将sessionFactory注入其中
<bean id="userManager" class="com.bjpowernode.usermgr.manager.UserManagerImpl">
<property name="sessionFactory" ref="sessionFactory" />
<property name="logManager" ref="logManager"></property>
</bean>
为什么这能注入sessionFactory,因为DAO继承了HibernateDaoSupport,而这个类有一个setSessionFactory()方法,所以实现了注入(在实例化HibernateDaoSupport时就实例化得到sessionFactory了):
private HibernateTemplate hibernateTemplate;
public final void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = createHibernateTemplate(sessionFactory);
}
4.配置Spring,进行事务的配置,Spring针对Hibernate实现了事务管理器,将sessionFactory注入到事务管理器中,同时利用AOP配置事务的管理
<!-- 配置sessionfactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- name为sessionFactory是由底层的set决定的,第二个sessionFactory是上面配置的 -->
<!-- 将sessionFactory注入到事务管理器中 -->
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 哪些类哪些方法使用事务 -->
<aop:config>
<aop:pointcut id="allManagerMethod"
expression="execution(* com.bjpowernode.usermgr.manager.*.*(..))" />
<!-- 将pintcut和advice注入进来 -->
<aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice" />
</aop:config>
<!-- 对事物的传播性进行设置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="modify*" propagation="REQUIRED" />
<!-- 其它的,就剩查询方法了,设置只读属性,如果内存改变,不更新update -->
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
【注】
- HibernateTransactionManager通过注入sessionfactory,然后在得到session,把session包装成SessionHolder(),并通过threadlocal来对象的实现和线程的绑定最后到线程中的session取得的Transaction
- Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现
- Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了
【总结】
Spring为Hibernate的DAO提供工具类:HibernateDaoSupport。该类主要提供了两个方法:
public final void setSessionFactory(SessionFactory sessionFactory)
public final HibernateTemplate getHibernateTemplate()
- getHibernateTemplate()方法返回hibernateTemplate对象,而hibernateTemplate对象是由setSessionFactory(SessionFactory sessionFactory)调用createHibernateTemplate()方法,此方法又new HibernateTemplate(sessionFactory)创建HibernateTemplate的实例,hibernateTemplate对象已帮助我们实现了事务的开启,关闭,我们只关注对业务的操作即可
- 我们也可使用
this.getSession().save(user);
获取事务并进行操作,但是就意味放弃了spring自动管理事务的好处。getSession()也是HibernateDaoSupport类的一个方法:protected final Session getSession()
- session打开策略为:Spring会根据实际的操作,采用“每次事务打开一次session”的策略,自动提高数据库访问的性能