spring提供了对事务的支持,在spring中主要有两种方式使用事务,一、编程式事务控制;二、声明式事务控制。
编程式事务:允许用户在代码中精确定义事务的边界,侵入到了业务代码里面,但是提供了更加详细的事务管理
声明式事物:基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现,有助于用户将操作与事务规则进行解耦。
Spring事物控制采用动态代理,因此同一个service内部,事物方法之间的套用调用,不管时普通方法还是事物方法之间的嵌套调用,都不会开启新的事物
例如:saveItems2开启有一个事物,newTransItems开启一个新的事物,
结果:newTransItems保存成功,saveItems2也保存成功
预期:newTransItems回滚,saveItems2保存成功
@Override
public int saveItems2(Items items) throws Exception {
try{
this.newTransItems(items);//this是真实对象或者目标对象,不是代理对象
}catch(Exception e){
e.printStackTrace();
}
items.setName("serice_saveItem22");
return itemsMapper.saveItemInfo(items);
}
@Override
public int newTransItems(Items item) throws Exception {
itemsMapper.saveItemInfo(item);
System.out.println("调用者"+this.getClass().getName());
int a = 2/0;
return 1;
}
实现以上有多种方法:
第一种方法:通过获取当前的AopProxy代理对象:
通过Aop代理来调用newTransItems方法通过获取当前的AopProxy代理对象,通过Aop代理来调用newTransItems方法
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" />
需要在配置文件中加入
((Item2Service)AopContext.currentProxy()).newTransItems(items);
第二种方法:通过ApplicationContext,在spring容器中 获取当前类的代理类
SpringContextHolder.getBean(Item2Service.class).newTransItems(items);
需要在配置文件中加入
<bean id="springContextHolder" class="com.zixue.ssm.util.SpringContextHolder" />
配置事物的几种方式:
1使用tx标签配置拦截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
">
<!-- 基于@AspectJ切面的驱动器,开启AOP拦截,CGLIB@Aspect -->
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" />
<!-- 使用了@Aspect注解的切面类,启动时加载bean:类中配置@annotation切入点:
同@annotation(org.springframework.transaction.annotation.Transactional)一致、前置后置增强方法-->
<bean class="com.zixue.ssm.aop.AnnotationTestAspect"/>
<!--读取配置参数,数据库,redis地址等 -->
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:oracle.properties</value>
</property>
</bean>
<!--配置一个数据源,根据上面propertyConfig指定的location去找数据库连接的配置信息-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>${driver}</value>
</property>
<property name="url">
<value>${url}</value>
</property>
<property name="username">
<value>${username}</value>
</property>
<property name="password">
<value>${password}</value>
</property>
</bean>
<!-- 声明式管理事物 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 通知 -->
<tx:advice id= "txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" read-only="true" timeout="1" />
<tx:method name="newTrans*" propagation="REQUIRES_NEW" read-only="true"
rollback-for="Exception" />
<tx:method name="*_NESTED" propagation="NESTED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.zixue..*Service*.*(..)) or @annotation(org.springframework.transaction.annotation.Transactional)"/>
</aop:config>
<!-- 加载Spring配置文件时,如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口。用于获取ApplicationContext 对象 -->
<bean id="springContextHolder" class="com.zixue.ssm.util.SpringContextHolder" />
</beans>
第二种使用拦截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
">
<!-- 使用了@Aspect注解的切面类,启动时加载bean:类中配置@annotation切入点:
同@annotation(org.springframework.transaction.annotation.Transactional)一致、前置后置增强方法-->
<bean class="com.zixue.ssm.aop.AnnotationTestAspect"/>
<!--读取配置参数,数据库,redis地址等 -->
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:oracle.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>${driver}</value>
</property>
<property name="url">
<value>${url}</value>
</property>
<property name="username">
<value>${username}</value>
</property>
<property name="password">
<value>${password}</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- Bean 代理事务 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true" />
<property name="exposeProxy" value="true" />
<property name="beanNames">
<list>
<value>*Dao*</value>
<value>*Service*</value>
<value>*Delegate*</value>
<value>*IfOperate</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 事务拦截器 ,配置事务属性 -->
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<!-- PROPAGATION_REQUIRED 支持现在的事务,如果没有就建立一个新的事务 -->
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="edit*">PROPAGATION_REQUIRED</prop>
<prop key="do*">PROPAGATION_REQUIRED</prop>
<prop key="newTrans*">PROPAGATION_REQUIRES_NEW</prop>
</props>
</property>
</bean>
<!-- 加载Spring配置文件时,如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口。用于获取ApplicationContext 对象 -->
<bean id="springContextHolder" class="com.zixue.ssm.util.SpringContextHolder" />
</beans>
第三种全注解:
<context:annotation-config />
<context:component-scan base-package="com.bluesky" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
事物控制主要有3个接口:
PlantformTransactionManager:用于平台相关的事物管理器,spirng并不直接管理事务,而是提供了多种管理器,它事务管理的职责委托给相关平台框架去实现,通过这个接口,相关平台或框架自己实现
TransactionDefinition:事务传播行为(隔离、传播、超时、只读),事务隔离类型(5种),超时设置/只读状态
TransactionStatus:事物具体运行状态-事物管理过程中,每个时间点事物的状态信息
用户通过配置事物管理器(TransActionManager)进行事物管理,然后通过TransactionDefinition(事物定义信息,事物的管理方案)进行 事物管理,最后事物运行过程中,每个时刻都可以通过获取Transaction(事物状态)来了解事物运行状态