• (Spring笔记)Spring集成MyBatis案例——第2节之基于注解式的事务传播


    一、前言

            本章是在上一节SM工程项目中,通过@Transactional进行学习事务传播特性。

            Spring声明注解式事务管理建立在AOP基础之上,是一个典型的横切关注点,通过环绕增强来实现,其原理是对方法前后进行拦截,然后在目标方法开始之前创建或加入一个事务,在执行完毕之后根据执行情况提交或回滚事务。


    二、非事务应景

            (1)当前表数据

            (2)更改业务接口实现——accounts

            说明:以accounts账户表为例,在没有使用事务控制条件下执行操作过程中数据的不安全性。

    1. @Service //交给Spring去创建对象
    2. public class AccountsServiceImpl implements AccountsService {
    3. //在所有的业务逻辑层中一定会有数据访问层的对象
    4. @Autowired
    5. private AccountsMapper accountsMapper;
    6. @Override
    7. public int addAccounts(Accounts accounts) {
    8. int num = 0;
    9. num = accountsMapper.addAccounts(accounts);
    10. System.out.println("增加帐户成功!");
    11. //手工抛出异常
    12. System.out.println(1 / 0);
    13. return num;
    14. }
    15. }

            说明:以上代码addAccounts()方法中,先添加成功数据,之后此方法发生异常。从数据安全性和业务严谨性考虑应当为整个addAccounts()方法体不发生任何错误或异常时,新增数据才能正常处理。这里代码先添加数据再发生异常,就在accounts表中已经有了数据,所以我们需要使用事务来控制整个业务对数据操作进行细节处理。


    三、事务应景——>注解式

            说明:以accounts账户表为例,在使用事务控制条件下执行操作过程中保障数据安全性。————>业务接口实现同上

            (1)更改Spring配置service

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    5. 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">
    6. <!--导入applicationContext_mapper.xml文件-->
    7. <import resource="applicationContext_mapper.xml"/>
    8. <!-- SM是基于注解的开发,所以添加包扫描 -->
    9. <context:component-scan base-package="com.dhrj.java.zsitking.service.impl"/>
    10. <!-- 事务处理 -->
    11. <!-- 1.将MyBatis数据源替换为Druid数据源的Spring单例bean对象加载到Spring事务管理器中 -->
    12. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    13. <property name="dataSource" ref="dataSource"/>
    14. </bean>
    15. <!-- 2.将Spring事务管理器单例bean对象加载到Spring事务注解驱动中
    16. 使用@Transaction注解以及它的各类事务属性值,
    17. 再通过代理模式进行底层事务拦截控制,当业务合法后正常添加数据,完成业务实现
    18. -->
    19. <tx:annotation-driven transaction-manager="transactionManager"/>
    20. </beans>

            说明:既然是基于注解控制SQL事务,那就必须先完成Spring事务管理器和注册事务驱动的注解模式。

            (2)@Transactional

            说明:业务中需要进行事务管理的类或方法都必须是公开Public修饰的,并且必须使用Spring内置@Transactional注解标注该类或方法,因为已经在Spring配置文件中添加了事务管理器和注解驱动,那么被@Transactional注解标注该类或方法在程序运行过程中会被Spring管理,程序员只需配置相应的事务控制参数,交给Spring容器中的代理模式(JDK+CGLib)进行SQL事务的处理。若不使用@Transactional注解标注该类或方法,那么代理模式无法访问,就不能代理业务。

                    ——不使用@Transactional注解时

    1. AccountsService accountsService = (AccountsService) ac.getBean("accountsServiceImpl");
    2. System.out.println("accountsService单例bean对象的类型"+accountsService.getClass());

            说明:最后的对象类型是账户接口实现类本身,即验证Spring的JDK动态代理+事务控制没有生效

                    ——使用@Transactional注解时

            (3)@Transactional属性值

            说明:从上往下介绍常用重点属性value()transactionManager()lable()只是注解的别名标签,知道是什么就行,这里不详细介绍。

            (4)@Transactional开启事务

    1. @Transactional(propagation = Propagation.REQUIRED)//事务处于开启状态,生效
    2. @Service //交给Spring去创建对象
    3. public class AccountsServiceImpl implements AccountsService {
    4. //在所有的业务逻辑层中一定会有数据访问层的对象
    5. @Autowired
    6. private AccountsMapper accountsMapper;
    7. @Override
    8. public int addAccounts(Accounts accounts) {
    9. int num = 0;
    10. num = accountsMapper.addAccounts(accounts);
    11. System.out.println("增加帐户成功!");
    12. //手工抛出异常
    13. System.out.println(1 / 0);
    14. return num;
    15. }
    16. }
    1. @Test
    2. public void testAccounts() {
    3. //2.取出UsersServiceImpl
    4. AccountsService accountsService = (AccountsService) ac.getBean("accountsServiceImpl");
    5. System.out.println("accountsService单例bean对象的类型"+accountsService.getClass());
    6. int num = accountsService.addAccounts(new Accounts(666,"张松的账户666","账户余额666"));
    7. System.out.println(num);
    8. }

            结论:Spring事务的传播特性在业务开发中,保障了数据安全的原子性、一致性隔离性、持久性。

  • 相关阅读:
    Transformer和attention资料
    Java面试题(持续更新)
    PMSM中常用的两种坐标变换——Clarke变换
    Npm——常用指令
    spark安装
    java-继承类练习
    内核IPv4路由选择子系统(简述)
    486.预测赢家
    2023年9月青少年软件编程(C 语言) 等级考试试卷(二级)
    Kubernetes 词条总结
  • 原文地址:https://blog.csdn.net/qq_39038178/article/details/125613974