本章是在上一节SM工程项目中,通过@Transactional进行学习事务传播特性。
Spring声明注解式事务管理建立在AOP基础之上,是一个典型的横切关注点,通过环绕增强来实现,其原理是对方法前后进行拦截,然后在目标方法开始之前创建或加入一个事务,在执行完毕之后根据执行情况提交或回滚事务。
说明:以accounts账户表为例,在没有使用事务控制条件下执行操作过程中数据的不安全性。
- @Service //交给Spring去创建对象
- public class AccountsServiceImpl implements AccountsService {
-
- //在所有的业务逻辑层中一定会有数据访问层的对象
- @Autowired
- private AccountsMapper accountsMapper;
-
- @Override
- public int addAccounts(Accounts accounts) {
- int num = 0;
- num = accountsMapper.addAccounts(accounts);
- System.out.println("增加帐户成功!");
- //手工抛出异常
- System.out.println(1 / 0);
- return num;
- }
- }
说明:以上代码addAccounts()方法中,先添加成功数据,之后此方法发生异常。从数据安全性和业务严谨性考虑应当为整个addAccounts()方法体不发生任何错误或异常时,新增数据才能正常处理。这里代码先添加数据再发生异常,就在accounts表中已经有了数据,所以我们需要使用事务来控制整个业务对数据操作进行细节处理。
说明:以accounts账户表为例,在使用事务控制条件下执行操作过程中保障数据安全性。————>业务接口实现同上
- <?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: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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
-
- <!--导入applicationContext_mapper.xml文件-->
- <import resource="applicationContext_mapper.xml"/>
- <!-- SM是基于注解的开发,所以添加包扫描 -->
- <context:component-scan base-package="com.dhrj.java.zsitking.service.impl"/>
- <!-- 事务处理 -->
- <!-- 1.将MyBatis数据源替换为Druid数据源的Spring单例bean对象加载到Spring事务管理器中 -->
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"/>
- </bean>
- <!-- 2.将Spring事务管理器单例bean对象加载到Spring事务注解驱动中
- 使用@Transaction注解以及它的各类事务属性值,
- 再通过代理模式进行底层事务拦截控制,当业务合法后正常添加数据,完成业务实现
- -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
- </beans>
说明:既然是基于注解控制SQL事务,那就必须先完成Spring事务管理器和注册事务驱动的注解模式。
说明:业务中需要进行事务管理的类或方法都必须是公开Public修饰的,并且必须使用Spring内置@Transactional注解标注该类或方法,因为已经在Spring配置文件中添加了事务管理器和注解驱动,那么被@Transactional注解标注该类或方法在程序运行过程中会被Spring管理,程序员只需配置相应的事务控制参数,交给Spring容器中的代理模式(JDK+CGLib)进行SQL事务的处理。若不使用@Transactional注解标注该类或方法,那么代理模式无法访问,就不能代理业务。
- AccountsService accountsService = (AccountsService) ac.getBean("accountsServiceImpl");
- System.out.println("accountsService单例bean对象的类型"+accountsService.getClass());
说明:最后的对象类型是账户接口实现类本身,即验证Spring的JDK动态代理+事务控制没有生效。
——使用@Transactional注解时
说明:从上往下介绍常用重点属性,value()、transactionManager()、lable()只是注解的别名标签,知道是什么就行,这里不详细介绍。
- @Transactional(propagation = Propagation.REQUIRED)//事务处于开启状态,生效
- @Service //交给Spring去创建对象
- public class AccountsServiceImpl implements AccountsService {
-
- //在所有的业务逻辑层中一定会有数据访问层的对象
- @Autowired
- private AccountsMapper accountsMapper;
-
- @Override
- public int addAccounts(Accounts accounts) {
- int num = 0;
- num = accountsMapper.addAccounts(accounts);
- System.out.println("增加帐户成功!");
- //手工抛出异常
- System.out.println(1 / 0);
- return num;
- }
- }
- @Test
- public void testAccounts() {
- //2.取出UsersServiceImpl
- AccountsService accountsService = (AccountsService) ac.getBean("accountsServiceImpl");
- System.out.println("accountsService单例bean对象的类型"+accountsService.getClass());
- int num = accountsService.addAccounts(new Accounts(666,"张松的账户666","账户余额666"));
- System.out.println(num);
- }
结论:Spring事务的传播特性在业务开发中,保障了数据安全的原子性、一致性、隔离性、持久性。