Spring事务的理解

一、什么是事务:

我理解为:事务其实就是一件事情,要做就做完,中途出问题了就要恢复成原状态(等于没有做).

二、事务的四大特性

(1)、原子性:

	事务必须是一个不可分割的整体

(2)、一致性:

执行完数据库操作后,数据不会被破坏。打个比方,如果从 A 账户转账到 B 账户,不可能因为 A 账户扣了钱,而 B 账户没有加钱吧

(3)、隔离性:

对同一条数据的操作,不同的事务之间应该隔离(提交之前,数据变化仅仅在事务内部,与外部隔离),要不然会产生脏读、幻读等情况情况。
为了让事务之间没有干扰,
制定了以下几种事务隔离级别:

<1>、READ_UNCOMMITTED
<2>、READ_COMMITTED
<3>、REPEATABLE_READ
<4>、SERIALIZABLE

从上往下,级别越来越高,并发性越来越差,安全性越来越高

(4)、持久性:

当我们执行一条 insert 语句后,数据库必须要保证有一条数据永久地存放在磁盘中,这个也算事务的一条特性

(5)、总结:

原子性是基础,隔离性是手段,持久性是目的,真正的老大就是一致性。数据不一致了就要乱套了。

三、JDBC不同事务隔离级别要解决的问题:

(1) :脏读:就是当前事务中访问到了其它事务还没有提交的数据,并且在此基础上做了其它的数据操作。

在这里插入图片描述

(2):不可重复读:我理解为当前事务中读取到了其它事务已经提交修改的数据(其它事务修改前读取了一次
	,修改后又读取了一次,导致同一事务中两次读取的数据不一样)

在这里插入图片描述

(3):幻读:我理解为当前事务中读取到了其它事务提交新增的数据集(其它事务新增前读取了一次,
	新增后又读取了一次,导致同一事务中读取到的结果集行数不同)

在这里插入图片描述

	以上3种情况脏读是一定要避免的。	
	MySQL 数据库的默认事务隔离级别就是 READ_COMMITTED(只禁止脏读,也就是隔离其它事务没有提交的数据),READ_COMMITTED已经可以解决大部分的问题。

在这里插入图片描述

四、完善事务管理功能

(1)、事务传播行为

Spring 解决的只是方法之间的事务传播,比如A方法是一个事务,B方法是一个事务,A方法里面包含B方法。那么事务是怎么传播的?

(2)、PROPAGATION_REQUIRED:

最常用也是spring默认是事务传播级别,A方法执行的时候已经有事务了,所以B方法的事务会注入到A方法事务里面来(合成一个事务)。

(3)、Spring关于事务的附加功能

1、事务超时(Transaction Timeout):为了解决事务时间太长,消耗太多的资源,所以故意给事务设置一个最大时常,
   如果超过了,就回滚事务。   
   ------  timeout="1"
   
2、只读事务(Readonly Transaction):为了忽略那些不需要事务的方法,比如读取数据,这样可以有效地提高一些性能 
  	------  propagation="REQUIRED"

事务最重要的两个特性,是事务的传播级别和数据隔离级别。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。

五、如何配置Spring的事务管理:

(1)、在Spring配置文件中使用AOP的方式实现事务的配置:

<!-- 定义事务管理器 -->
<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!-- 定义通知 -->
<tx:advice id="TestAdvice" transaction-manager="transactionManager">
	<!--配置事务传播性,隔离级别以及超时回滚等问题 -->
	<tx:attributes>
		<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"   timeout="1"/>
		<tx:method name="del*" propagation="REQUIRED" />
		<tx:method name="update*" propagation="REQUIRED" />
		<tx:method name="add*" propagation="REQUIRED" />
		<tx:method name="*" rollback-for="Exception" />
	</tx:attributes>
</tx:advice>

<aop:config>
		<!--配置事务切点,将TestAdvice通知切入到com.website.service子目录下的所有方法 -->
		<aop:pointcut id="services"
			expression="execution(* com.website.service.*.*(..))" />
		<aop:advisor pointcut-ref="services" advice-ref="TestAdvice" />
</aop:config>

(2)、注解式事务:

<1>、首先在Spring配置文件中设置事务管理器,定义通知tx:annotation-driven

<!-- 定义事务管理器 -->
<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>
<!--使用事务注解, 注解方式配置事务-->
<tx:annotation-driven  transaction-manager="transactionManager" />

<2>、代码中的具体的注解以及事务的传播性、隔离级别一般在service 层中配置下面

@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,timeout=1,isolation=Isolation.DEFAULT)
	public void saveUser(Map<String, String> map) throws Exception {
         System.out.println("方法开始");
		for (int i = 0; i < 500000; i++) {
	            System.out.println("*");
	        }
		 System.out.println("进入保存");
		 userDao.saveUser(map);
		 System.out.println("退出保存");
	}

@Transactional 一般是放在public方法上面,也可以放在类上面,方法和类同时有@Transactional 注解时,方法上面的注解优先级高。

六、以上面的笔记来理解,Spring AOP是怎样来管理事务的.

 1、配置文件里面用aop的方式切入事务到service的指定方法,每个service方法都被事务管理。事务的隔离级别是READ_COMMITTED(只禁止脏数据),事务的传播级别是PROPAGATION_REQUIRED(遇到新的事务,会将其加入到当前事务,合并成一个事务)
 2、这个时候需要实现一个功能,先插入数据,再查询数据,有三种写法:
     <1>、action层里面调用两个server方法:
		@Action(value="getList")
		public void getList(){
		    this.Service.add();  //添加方法
			this.Service.getList(); //查询方法
		}
	分析:因为每个server是一个独立的事务,这里的action里面调用方法是按顺序执行的,
	所以是先执行添加事务并且提交事务后再执行查询事务,结果是可以查到刚添加的数据


<2>、action层里面调用一个server方法,这个server方法里面调用添加和查询server方法
	@Action(value="getList")
	public void getList(){
	    this.Service.serviceFun(); 
	}
	
	server方法层:
	public void serviceFun(){
		this.add();
		this.getList();
	}

分析:因为事务的传播级别是PROPAGATION_REQUIRED(遇到新的事务,会将其加入到当前事务,合并成一个事务),所以this.add()和this.getList();是在一个事务内执行的,不存在什么添加事务提交不提交,都在一个隔离墙内,所以结果是可以查到刚添加的数据。

<3>、如果添加删除操作都在一个servier里面之间调用dao层方法,本来就是一个事务,那就更加可以查到刚添加的数据了。

以上是我对于spring Aop切入事务后,为什么我们不用考虑事务管理是原因的理解,因为spring都帮我们搞定了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值