Spring5学习记录(四)声明式事务管理
- 一、事务管理
- 1、事务四个特性ACID
- 2、事务的两种方式
- 二、基于注解实现声明式事务管理
- 1、配置xml文件
- 2、添加事务注解 ` @Transactional `
- 三、声明式事务管理的参数配置
- 1、propagation:事务传播行为
- 2、isolation:事务隔离级别
- 3、timeout:超时时间
- 4、readOnly:是否只读
- 5、rollbackFor:回滚
- 6、noRollbackFor:不回滚
- 四、完全注解实现声明式事务管理
- 1、配置类:
- 2、添加注解
- 五、xml实现声明式事务管理
一、事务管理
事务是数据库操作最基本单位,要么都成功,要么都失败。典型场景:转账。
1、事务四个特性ACID
原子性,一致性,隔离性,持久性。
2、事务的两种方式
Spring事务管理有两种方式:编程式事务管理 和 声明式事务管理,一般使用声明式事务管理,底层使用AOP原理。
声明式事务管理有两种方式:基于xml配置方式 和 基于注解方式,一般使用注解方式。
Spring事务管理提供了一个接口,叫做事务管理器,这个接口针对不同的框架提供不同的实现类。
对于使用JdbcTemplate、MySQL进行数据库交互,使用DataSourceTransactionManager实现类,如果整合Hibernate框架则使用HibernateTransactionManager实现类,具体情况具体使用。
二、基于注解实现声明式事务管理
1、配置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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><context:component-scan base-package="com.atguigu.spring5"></context:component-scan><aop:aspectj-autoproxy></aop:aspectj-autoproxy><!-- 数据库连接池 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/book" /><property name="username" value="root" /><property name="password" value="000000" /><property name="driverClassName" value="com.mysql.jdbc.Driver" /></bean><!--创建JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入数据库连接池--><property name="dataSource" ref="dataSource"></property></bean><!--创建事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--开启事务注解--><tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
2、添加事务注解 @Transactional
在service类上面或者service类的方法上面添加事务注解@Transactional
- 如果把@Transactional添加在类上面,这个类里面所有方法都添加事务。
- 如果只是添加在方法上面,则只为这个方法添加事务。
@Service //ioc对象创建注解
@Transactional //事务注解
public class UserService {......
}
三、声明式事务管理的参数配置
1、propagation:事务传播行为
事务传播可以理解为方法A调用方法B的过程中,如果方法A是由事务A提交的,那么需要考虑被方法A调用的方法B的事务是怎样的。
事务传播行为有7种,不是与数据库交互,数据库定义的,而是spring框架自带的,是spring通过aop实现的,下边是7种事务传播行为:
- REQUIRED:如果当前没有事务,就新建一个事务。如果当前存在事务,则加入这个事务。
- NESTED:如果当前没有事务,就新建一个事务。如果当前事务存在,则执行一个嵌套事务。
- REQUIRES_NEW:如果当前没有事务,就新建一个事务。如果当前存在事务,把当前事务挂起,并且自己创建一个新的事务给自己使用。
- SUPPORTS:如果当前没有事务,就以非事务方式执行。 如果当前有事务,则使用事务。
- NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- MANDATORY:以事务方式执行,如果当前没有事务,就抛出异常。 NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
2、isolation:事务隔离级别
事务如果没有隔离的特性,会导致三个读数据问题:脏读,不可重复读,虚读(幻读)。
-
脏读:一个未提交的事务读取到了另一个未提交事务的数据。
-
不可重复读:事务A第一次读取数据,事务B对同一个表进行了update或delete(修改操作),事务A第二次读取数据,那么两次读取的数据是不同的,这时是不可重复读。
-
幻(虚)读:事务A第一次读取数据,事务B对同一个表进行了insert(添加操作),事务A第二次读取数据,那么两次读取的数据是不同的,这时是幻读。
MySQL数据库默认可重复读。
3、timeout:超时时间
事务需要在一定时间内进行提交,超过时间后回滚。
- 默认值是-1,设置时间以秒为单位。
4、readOnly:是否只读
- 默认值为false,表示可以查询,也可以增删改。
- 设置为true,只能查询。
5、rollbackFor:回滚
设置出现哪些异常进行事务回滚。
6、noRollbackFor:不回滚
设置出现哪些异常不进行事务回滚。
@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED)
public class AccountService {}
四、完全注解实现声明式事务管理
1、配置类:
@Configuration //配置类
@ComponentScan(basePackages = "com.oymn.spring5") //开启组件扫描
@EnableTransactionManagement //开启事务
public class Config {//创建数据库连接池@Beanpublic DruidDataSource getDruidDataSource(){DruidDataSource druidDataSource = new DruidDataSource();druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");druidDataSource.setUrl("jdbc:mysql://localhost:3306/book");druidDataSource.setUsername("root");druidDataSource.setPassword("000000");return druidDataSource;}//创建JdbcTemplate对象@Beanpublic JdbcTemplate getJdbcTemplate(DataSource dataSource){JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}//创建事务管理器@Beanpublic DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;}
}
2、添加注解
@Service
public class AccountService {@Autowiredprivate AccountDao accountDao;@Transactionalpublic void accountMoney(){accountDao.add();//int i=1/0; //用来模拟转账失败accountDao.reduce();}
}
五、xml实现声明式事务管理
从xml实现声明式事务管理的配置文件来看,spring实现事务管理是通过AOP切面实现的。
<context:component-scan base-package="com.oymn"></context:component-scan><!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/book" /><property name="username" value="root" /><property name="password" value="000000" /><property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean><!--创建JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入数据库连接池--><property name="dataSource" ref="dataSource"></property>
</bean><!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean><!--配置事务通知-->
<tx:advice id="txadvice"><!--配置事务参数--><tx:attributes><tx:method name="accountMoney" propagation="REQUIRED" /></tx:attributes>
</tx:advice><!--配置切入点和切面-->
<aop:config><!--配置切入点--><aop:pointcut id="pt" expression="execution(* com.oymn.spring5.Service.*.*(..))"/><!--配置切面--><aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>