上一篇文章我们进行了基本的框架搭建,实现了登录和全查功能。这都属于查询操作,如果要进行增删改等需要对数据库修改的操作时就需要进行事务操作。
我们在执行增删改操作的时候在方法中使用session缓存手动开启事务,等执行完持久化操作之后在进行事务的提交。这就是编程式事务,但是每个方法都进行一个事务的开启,提交,回滚等操作的话太过麻烦。
我们现在是SSH框架的整合,由Spring对Hibernate和Struts2进行管理,Spring可以拥有全部的控制权,其中就包括事务,Spring的Aop提供了对事务的支持,只需要在Spring配置文件中声明事务就可以实现对事务的统一管理,并且不需要再在DAO层的方法中手动的开启事务,能简化对数据的持久化操作。这是声明式事务。
继续使用上一片文章中搭建项目,打开applicationContext.xml,声明式事务的配置就需要增加applicationContext.xml的命名空间,tx和aop的命名空间,下面是增加命名空间后的头部信息
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
首先需要配置Hibernate事务管理器bean,并注入sessionFactory属性
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory">property>
bean>
这样就可以使用Spring管理Hibernate的事务,然后配置事务增强,就是配置事务的规则,指定那些方法执行事务和执行事务的规则
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="query*" read-only="true" propagation="REQUIRED"/>
<tx:method name="*Update" read-only="false" propagation="REQUIRES_NEW" />
<tx:method name="*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
然后定义事务的切入点,事务的切入点使用execution表达式进行描述,表达式描述事务的切入点方法所在类的全路径,因为service层有可能执行多个dao层的方法,所以我们这里定义service层的所有方法
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(* org.hua.service.*.*(..))" id="pointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut="pointcut"/>
aop:config>
注意如果事务切入的类实现了至少一个接口那么就会出现
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type
或者Java.lang.ClassCastException: 异常,有两个解决办法
自此就完成Spring的声明式事务的配置
spring配置文件头部信息跟上边一样
同样配置事务管理器,然后开启注解事务
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory">property>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
然后在需要开启事务的类或方法上边直接加上@Transactional即可
事务规则可以在注解里面进行配置,具体规则参照上面
@Transactional(readOnly=true,rollbackFor=Exception.class,propagation=Propagation.REQUIRED)
public void empDel(int id) {
edi.empDel(id);
}
Spring提供的@Transaction注解事务管理,内部同样是利用环绕通知TransactionInterceptor实现事务的开启及关闭。
使用@Transactional注意点: