spring事物管理那点事

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(事物状态)来了解事物运行状态

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值