在谈Spring事务管理以前咱们想一下在咱们不用Spring的时候,在Hibernate中咱们是怎么进行数据操做的。在Hibernate中咱们每次进行一个操做的的时候咱们都是要先开启事务,而后进行数据操做,而后提交事务,关闭事务,咱们这样作的缘由是由于Hibernate默认的事务自动提交是false,他是须要咱们人为的手动提交事务,假如你不想每次都手动提交事务的话,你能够在hibernate.cfg.xml我文件中把它设置为事务自动提交: <property name="hibernate.connection.autocommit">true</property> spring
当咱们Spring对咱们的Hibernate进行整合以后,咱们的代码又出现了什么变化呢?整合,以后,咱们再也不是每次都去拿Session进行数据操做了,也不须要每次都开启事务,提交事务了,咱们只须要Spring给咱们提供的一个HibernateTemplate,咱们直接用这个类里面给咱们提供的数据操做方法就能够操做数据了。咱们在也看不到关于事务的代码了(spring 封装了事务处理),那Spring究竟有没有在他的操做方法里面封装事务处理呢?有的人直接HibernateTemplate里面提供的方法操做数据,成功了,有的人却又失败了,这究竟是怎么回事呢?其实这里要看咱们是怎样集成咱们的Hibernate和Spring,若是在集成的过程当中,咱们抛弃了hibernate.cfg.xml文件,直接在Spring的的配置文件中进行配置数据源的话,那你直接用HibernateTemplate里面提供的方法是能够成功操做数据的,若是你仍是用hibernate.cfg.xml来配置数据源,在Spring的配置文件中引用hibernate.cfg.xml文件,那么你不能成功,这其中的缘由就是由于若是你用 hibernate.cfg.xml文件配置数据源,就像咱们前面说的,Hibernate默认是手动提交事务,而HibernateTemplatel提供的方法里面并无提供事务提交(此时spring 与 hibernate是代理关系,hibernate代理了事务),而若是你用Spring的配置文件来配置数据源,Sping默认是自动提交的,因此就会成功,若是你想把Spring设置为手动提交你能够在起配置文件中进行配置:express
<property name="defaultAutoCommit">
<value>false</value>
</property>编程
------------------以上都是把单条语句看做事务,下面是多条语句,须要声明事务管理--------------------缓存
纵然咱们把它的事务提交方式设置为自动,它能够进行数据操做,可是这样并不知足咱们实际的业务需求,由于有时候在我保存一个数据以后,我但愿他能继续保存另外一条数据,我但愿在保存完两条或者多条以后一块儿进行事务提交,这样即便出错,咱们能够回滚,取保数据的一致性,要么都成功要么都失败,这时候咱们就不能每保存完一条数据以后事务就自动提交,由于这样它们不在同一个事务当中,咱们不能保证数据的一致行。因此这时候咱们就须要手动的来配置咱们的事务,这就须要用到Spring为Hibernate提供的事务管理机制,Spring提供的事务管理能够分为两类:编程式的和声明式的,编程式,其实就是在代码里面来控制,像Hibernate操做数据同样,开启事务,提交事务,这种方式有必定的局限性,因此咱们通常是用声明式来配置咱们的事务。session
声明式事务配置主要分如下几步:spa
一、声明式事务配置hibernate
配置事务管理器;
事务的传播特性;
那些类那些方法使用事务。代理
<!-- 配置事务管理器 指定其做用的sessionFactory把事务交给Spring去处理 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <!-- 配置事务的传播特性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 那些类的哪些方法参与事务 --> <aop:config> <aop:pointcut id="allServiceMethod" expression="execution(* com.coe.service.*.*(..))"/> <aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice"/> </aop:config>
咱们在配置事务的时候,咱们通常是把事务边界设置到service层,也就是你的业务逻辑层,由于咱们不少时候都是在咱们的业务逻辑层来完成咱们一些列的数据操做,若是放到Dao数据层,其粒度过小了。另外,若是咱们把事务配置在业务逻辑层的话,对咱们的二级缓存也是有好处的,这个你们之后实际操做的时候会发现。code
二、编写业务逻辑方法orm
这时候咱们就能够在咱们业务逻辑层用HibernateTemplate里面提供的数据操做方法来编写咱们的业务逻辑方法了,固然咱们的方法必需要是以咱们事务配置里面配置的同样,用save,delete,update,get作咱们的方法的开头。须要注意的是,默认状况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的。