18_Spring_事务管理注解方式
18_Spring_事务管理注解方式
事务的管理应该放在我们的service层进行处理
spring中有两种事务的管理方式
1 编程式事务管理(了解)
2 声明式事务管理(掌握)
基于注解方式实现(掌握)
XML方式实现(了解)
Spring声明式事务的实现方式,底层就是AOP,AOP的底层就是动态代理
Spring事务管理相关的API
事务管理器接口: PlatformTransactionManager 针对不同的框架,提供了不同的实现类
注解方式实现事务控制
在applicationContext.xml配置事务相关的配置
- <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:c="http://www.springframework.org/schema/c" -
xmlns:util="http://www.springframework.org/schema/util" -
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/util -
http://www.springframework.org/schema/util/spring-util.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 - ">
-
<!--spring 注解扫描--> -
<context:component-scan base-package="com.msb"/> -
<!--读取jdbc配置文件--> -
<context:property-placeholder location="classpath:jdbc.properties"/> -
<!--配置德鲁伊连接池--> -
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> -
<property name="username" value="${jdbc_username}"></property> -
<property name="password" value="${jdbc_password}"></property> -
<property name="url" value="${jdbc_url}"></property> -
<property name="driverClassName" value="${jdbc_driver}"></property> -
</bean> -
<!--配置JDBCTemplate对象,并向里面注入DataSource--> -
class="org.springframework.jdbc.core.JdbcTemplate"><bean id="jdbcTemplate" -
<!--通过set方法注入连接池--> -
<property name="dataSource" ref="dataSource"></property> -
</bean> -
<!--配置一个事务管理器--> -
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><bean id="transactionManager" -
<!--将数据源注入事务管理器--> -
<property name="dataSource" ref="dataSource"></property> -
</bean> -
<!--开启事务注解--> -
<tx:annotation-driven transaction-manager="transactionManager"/>
在Service层中添加事务的注解
- package com.msb.service.impl;
- import com.msb.dao.AccountDao;
- import com.msb.service.AccountService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- /**
-
- @Author: Ma HaiYang
-
- @Description: MircoMessage:Mark_7001
- */
- @Service
- //@Transactional //加在类上,代表类中的所有方法都添加了事务控制
- public class AccountServiceImpl implements AccountService {
-
@Autowired -
private AccountDao accountDao; -
@Override -
@Transactional// 放在方法上,就是仅仅对当前方法增加了事务控制 -
public int transMoney(int from, int to, int money) { -
int rows=0; -
rows+=accountDao.transMoney(from, 0 - money); -
int i =1/0; -
rows+=accountDao.transMoney(to, money); -
return rows; -
} - }
再次测试,就算是service方法运行出现异常,自动会回滚,如果没有,那么自动提交
@Transactional 注解的一些参数和参数的含义
@Transactional(propagation = Propagation.REQUIRED,isolation =
Isolation.READ_UNCOMMITTED,readOnly = true,rollbackFor =
ClassCastException.class,noRollbackFor = NullPointerException.class,timeout =
10)
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- @Documented
- public @interface Transactional {
-
@AliasFor("transactionManager") -
String value() default ""; -
@AliasFor("value") -
String transactionManager() default ""; -
String[] label() default {}; -
Propagation propagation() default Propagation.REQUIRED; -
Isolation isolation() default Isolation.DEFAULT; -
int timeout() default -1; -
String timeoutString() default ""; -
boolean readOnly() default false; -
Class<? extends Throwable>[] rollbackFor() default {}; -
String[] rollbackForClassName() default {}; -
Class<? extends Throwable>[] noRollbackFor() default {}; -
String[] noRollbackForClassName() default {}; - }
propagation 事务的传播行为(面试)
多事务方法之间调用,事务是如何管理的
| 事务传播行为类型 | 说明 |
|---|---|
| PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择(默认)。 |
| PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
| PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
| PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
| PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
| PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
| PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
如果service层 add方法调用了 addDept和addEmp两个方法
PROPAGATION_REQUIRED
如果add方法有事务,那么addDept和addEmp就加入到add方法里的事务
如果add方法没有事务,那么就新建一个事务,将addDept和addEmp加入到这个新的事务中
PROPAGATION_REQUIRES_NEW
无论add是否有事务,都建立一个新的事务,所有的方法都加入到新的事务中,add原来的事务就不用了
isolation 事务的隔离级别
- DEFAULT (默认)
这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
MySQL默认REPEATABLE_READ
Oracle默认READ_COMMITTED
-
READ_UNCOMMITTED (读未提交)
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 -
READ_COMMITTED
(读已提交)
保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。 -
REPEATABLE_READ (可重复读)
这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
SERIALIZABLE(串行化)
这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。
timeout 超时时间
事务一定要在多长时间之内提交,如果不提交就会回滚
readOnly 只读事务
事务是否只能读取数据库的数据,如果为true,则不允许进行增删改
rollbackFor 指定发生回滚的异常
当方法发生哪些异常时才会回滚
noRollbackFor 指定不发生回滚的异常
当方法发生哪些异常时,不会回滚