18 事务

目录

编程事务(手动事务)--代码冗余

事务底层原理

声明式事务(xml+注解)

xml方式

注解

事务传播行为 七种


事务特性:

  原子性:要不全部成功,要不全部失败,不可再分

  一致性:A 500 B 0  转账B  B=500 A=0  A+B=500

  隔离性:多个事务之间互不影响

  持久性:保存到数据库的数据后不能做其他操作

Spring事务传播机制

Spring隔离级别

Spring事务 (面):

编程事务(手动事务)--代码冗余

 <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>


 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Component
public class TransactionUtils {
    // 事物管理器
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;
    //开启事务
    public TransactionStatus begin() {
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
        return transaction;
    }
    public void commit(TransactionStatus transaction) {
        dataSourceTransactionManager.commit(transaction);
    }
    public void rollback(TransactionStatus transaction) {
        dataSourceTransactionManager.rollback(transaction);
    }
}

 

<?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:p="http://www.springframework.org/schema/p"
	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.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 开启注解 -->
	<context:component-scan base-package="com.itmayiedu"></context:component-scan>
	<!-- 1. 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>

	<!-- 2. JdbcTemplate工具类实例 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

   <!-- 配置事物 -->
   <bean  id="DataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
   </bean>
</beans>       

使用事务

 @Autowired
   private TransactionUtils transactionUtils;
	public void add() {
        TransactionStatus begin =null;
	    try{
             begin = transactionUtils.begin();
            System.out.println("UserService2 ..add");
             int i =1/0;
            userDao.add();
            transactionUtils.commit(begin);
        }catch (Exception e){
            transactionUtils.rollback(begin);
        }
	}

事务底层原理

事务原理:aop编程+环绕通知+异常通知(重点)

aop管理事务:业务逻辑层不要加try,将异常抛给上一层,否则事务不起作用;在控制层进行捕获

环绕通知 begin和commit 异常通知:rollback

@Component
public class TransactionUtils {
	// 事物管理器
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;
	public TransactionStatus begin() {
		TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
		return transaction;
	}
	public void commit(TransactionStatus transaction) {
		dataSourceTransactionManager.commit(transaction);
	}
	public void rollback(TransactionStatus transaction) {
		dataSourceTransactionManager.rollback(transaction);
	}
}


import com.util.TransactionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;

	public class Aop02 {
		@Autowired
		private TransactionUtils transactionUtils;
		private   TransactionStatus begin;


		public void begin() {
			System.out.println("前置通知....");
		}

		public void commit() {
			System.out.println("后置通知....");
		}

		public void afterRun() {
			System.out.println("运行通知....");
		}

		public void afterThrowing() {
			System.out.println("异常通知");
			transactionUtils.rollback(begin);
		}

		public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
			begin = transactionUtils.begin();
			System.out.println("我是环绕通知-前");
			proceedingJoinPoint.proceed();
			System.out.println("我是环绕通知-后");
			transactionUtils.commit(begin);

		}
}

声明式事务(xml+注解)

xml方式

<?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:p="http://www.springframework.org/schema/p"
	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.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 1. 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>

	<!-- 2. JdbcTemplate工具类实例 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 3.配置事物 -->
	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
		<tx:attributes>
     <!-- get和find不需要事务 -->
			<tx:method name="get*" read-only="true" />
			<tx:method name="find*" read-only="true" />
			<tx:method name="*" read-only="false" />
		</tx:attributes>
	</tx:advice>
	<!-- Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.itmayiedu02.service.UserService.add(..))"
			id="pt" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
	</aop:config>

</beans>

注解

步骤:

         1) 必须引入Aop相关的jar文件

         2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类

         3)在需要添加事务控制的地方,写上: @Transactional

@Transactional注解:

         1)应用事务的注解

         2)定义到方法上: 当前方法应用spring的声明式事务

         3)定义到类上:   当前类的所有的方法都应用Spring声明式事务管理;

         4)定义到父类上: 当执行父类的方法时候应用事务。

<?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:p="http://www.springframework.org/schema/p"
	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.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
     	 http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 开启注解 -->
	<context:component-scan base-package="com.itmayiedu"></context:component-scan>
	<!-- 1. 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>

	<!-- 2. JdbcTemplate工具类实例 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 配置事物 -->
	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 开启注解事物 -->
    <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>   

 

@Transactional
	public void add() {
		try {
			userDao.add("lisi", 18);
			int i = 1 / 0;
			userDao.add("yushengjun", 19);
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//事物手动回滚代码
		}
		
	}

使用事物注意事项

 事物是程序运行如果没有错误,会自动提交事物,如果程序运行发生异常,则会自动回滚。

 如果使用了try捕获异常时.一定要在catch里面手动回滚。

 事物手动回滚代码

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

事务传播行为 七种

Spring中事务的定义:

Propagationkey属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:

  • PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
  • PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。(如果当前有事物,我就用当前事物,如果当前没有事物,就以非事物进行执行)
  • PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 
  • PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 
  • PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
  • PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
 @Transactional(propagation = Propagation.REQUIRED)

事务传播行为:

         Propagation.REQUIRED

                   指定当前的方法必须在事务的环境下执行;

                   如果当前运行的方法,已经存在事务, 就会加入当前的事务;

         Propagation.REQUIRED_NEW

                   指定当前的方法必须在事务的环境下执行;

                   如果当前运行的方法,已经存在事务:  事务会挂起; 会始终开启一个新的事务,执行完后;  刚才挂起的事务才继续运行。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值