SpringBoot基础之声明式事务和切面事务和编程式事务

news2024/7/31 19:32:48

文章目录

  • 前言
  • 一、事务特性
  • 开启事务
  • 二、事务的隔离级别
  • 三、事务的传播行为
  • 四、 Springboot事务
    • 1.Springboot声明式事务
      • 优点:
      • 缺点:
      • 实现方式:
      • @Transactional的参数
      • 声明式事务的约定流程:
    • 2. Springboot编程式事务
    • SpringBoo切面编程式事务


前言

事务管理对于企业应用来说是至关重要的,当出现异常情况时,它也可以保证数据的一致性。
springBoot中两种事务的实现方式,编程式事务配置和声明式事务配置还有切面事务 还有以后的分布式事务

详情参考 这篇


一、事务特性

在这里插入图片描述

  • 原子性(Atomicity):
    事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用;
  • 一致性(Consistency):
    一旦事务完成(不管是成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏;
  • 隔离性(Isolation):
    可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏;
  • 持久性(Durability):
    一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中;

Spring 框架中,涉及到事务管理的 API 大约有100个左右,其中最重要的有三个:TransactionDefinition、PlatformTransactionManager、TransactionStatus。所谓事务管理,其实就是”按照给定的事务规则来执行提交或者回滚操作”。”给定的事务规则”就是用 TransactionDefinition 表示的,”按照……来执行提交或者回滚操作”便是用 PlatformTransactionManager 来表示,而 TransactionStatus 用于表示一个运行着的事务的状态。打一个不恰当的比喻,TransactionDefinition 与 TransactionStatus 的关系就像程序和进程的关系。

开启事务

@EnableTransactionManagement

二、事务的隔离级别

和数据库中的事务级别是一样的 都会出现事务本身应该有的问题
在这里插入图片描述

三、事务的传播行为

在这里插入图片描述

四、 Springboot事务

1.Springboot声明式事务

声明式事务是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

根据代理机制的不同,总结了五种Spring事务的配置方式,如下图:

在这里插入图片描述

声明式事务@Transactional可以使用在类上,也可以使用在public方法上. 如果是使用在类上,则是对所有的public方法都开启事务,如果类和方法上都有则方法上的事务生效
在类上

@Transactional(rollbackFor=Exception.class)
public class TransactionServiceImpl implements TransactionService {
}

在方法上

@Override
@Transactional(rollbackFor=Exception.class)
public void t1(Student one) {
}

声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

优点:

编程式事务每次实现都要单独实现,但业务量大且功能复杂时,使用编程性事务无疑是痛苦的;而声明式事务不同,声明式事务属于非侵入性,不会影响业务逻辑的实现,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中;

非侵入式的开发方式,声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持;

缺点:

最细粒度只能是作用到方法级别,无法做到像编程事务那样可以作用到代码块级别;

实现方式:

使用拦截器:基于TransactionInterceptor 类来实施声明式事务管理功能(Spring最初提供的实现方式);

Bean和代理:基于 TransactionProxyFactoryBean的声明式事务管理

使用tx标签配置的拦截器:基于tx和aop名字空间的xml配置文件(基于Aspectj AOP配置事务);
全注解:基于@Transactional注解;

@Transactional的参数

在这里插入图片描述

声明式事务的约定流程:

首先Spring通过事务管理器(PlatformTransactionManager的子类)创建事务,与此同时会把事务定义中的隔离级别、超时时间等属性根据配置内容往事务上设置。而根据传播行为配置采取一种特定的策略,后面会谈到传播行为的使用问题,这是Spring根据配置完成的内容,你只需要配置,无须编码。然后,启动开发者提供的业务代码,我们知道Spring会通过反射的方式调度开发者的业务代码,但是反射的结果可能是正常返回或者产生异常返回,那么它给的约定是只要发生异常,并且符合事务定义类回滚条件的,Spring就会将数据库事务回滚,否则将数据库事务提交,这也是Spring自己完成的
  在这里插入图片描述

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,它的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

2. Springboot编程式事务

编程式事务:
是侵入性事务管理,直接使用底层的PlatformTransactionManager、使用TransactionTemplate(Spring推荐使用);
编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法;

@Autowired 
private TransactionTemplate transactionTemplate;
@Override
  public final void save2() {
   transactionTemplate.execute((status)->{
            mapper.saveStudent(newOne());
            mapper.saveStudent(newOne());
            return Boolean.TRUE;
        });
  }

这样两个mapper.saveStudent(newOne());就在一个事务中执行了

SpringBoo切面编程式事务

SpringBoo切面编程式事务应该是声明式事务的一种具体体现
此种方式基于AOP功能,所以需要添加
详细看这篇

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

配置类

@Aspect
@Configuration
public class MyTransactionConfig {

    /**
     * 配置方法过期时间,默认-1,永不超时
     */
    private final static int TX_METHOD_TIME_OUT = 10;

   /**
     * 全局事务位置配置 在哪些地方需要进行事务处理
     * 配置切入点表达式
     */
    private static final String POITCUT_EXPRESSION = "execution(* zdc.enterprise.service.impl.*.*(..))";

    @Autowired
    private PlatformTransactionManager platformTransactionManager;


    @Bean
    public TransactionInterceptor txadvice() {

        /*只读事物、不做更新删除等*/
        /*事务管理规则*/
        RuleBasedTransactionAttribute readOnlyRule = new RuleBasedTransactionAttribute();
        /*设置当前事务是否为只读事务,true为只读*/
        readOnlyRule.setReadOnly(true);
        /* transactiondefinition 定义事务的隔离级别;
         *如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。*/
        readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);

         /*增删改事务规则*/
        RuleBasedTransactionAttribute requireRule = new RuleBasedTransactionAttribute();
        /*抛出异常后执行切点回滚 建议自定义异常*/
        requireRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        /*PROPAGATION_REQUIRED:事务隔离性为1,若当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。 */
        requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        /*设置事务失效时间,超过10秒*/
        requireRule.setTimeout(TX_METHOD_TIME_OUT);

        /** 配置事务管理规则
         nameMap声明具备需要管理事务的方法名.
         这里使用addTransactionalMethod  使用setNameMap
         */
        Map<String, TransactionAttribute> nameMap = new HashMap<>();
        nameMap.put("add*", requireRule);
        nameMap.put("save*", requireRule);
        nameMap.put("insert*", requireRule);
        nameMap.put("update*", requireRule);
        nameMap.put("delete*", requireRule);
        nameMap.put("remove*", requireRule);

        /*进行批量操作时*/
        nameMap.put("batch*", requireRule);
        nameMap.put("get*", readOnlyRule);
        nameMap.put("query*", readOnlyRule);
        nameMap.put("find*", readOnlyRule);
        nameMap.put("select*", readOnlyRule);
        nameMap.put("count*", readOnlyRule);

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
        source.setNameMap(nameMap);

        TransactionInterceptor transactionInterceptor = new TransactionInterceptor(platformTransactionManager, source);

        return transactionInterceptor;
    }

    /**
     * 设置切面=切点pointcut+通知TxAdvice
     * @return
     */
    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(POITCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txadvice());
    }
}

有了这个切面配置类,就不要用在类或者每个方法上使用@Transactional了,当然方法名前缀要能和设置的匹配上. RuleBasedTransactionAttribute的参数大致和@Transactional的参数相同,里面有详细的注释,就不过多解释了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计SSM教学团队管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

微服务框架 SpringCloud微服务架构 11 自定义镜像 11.2 Dockerfile

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构11 自定义镜像11.2 Dockerfile11.2.1 什么是Dcokerfile11.2.2 直接开干11.…

【机器学习】支持向量机【上】硬间隔

有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 在阅读本篇之前建议先学习&#xff1a; 【机器学习】拉格朗日对偶性 【机器学习】核函数 由于字数限制&#xff0c;分成两篇博客。 【机器学习】支持向量机【上】硬间隔 【机器学习】支持向量机【下】…

绿色荧光染料FITC-PEG-FA,Folic acid-PEG-Fluorescein,荧光素-聚乙二醇-叶酸

​ 1、名称 英文&#xff1a;FITC-PEG-FA&#xff0c;Folic acid-PEG-Fluorescein 中文&#xff1a;荧光素-聚乙二醇-叶酸 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a; Fluorescent PEG Folic acid&#xff08;FA&#xff09; PEG 4、分子量&#xff1a;可定制&a…

[附源码]计算机毕业设计网上书城网站Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Java实现猜数游戏

1 问题 编写一个Java程序&#xff0c;实现以下功能&#xff1a; 2 方法 首先导入java.util包下的Random&#xff0c;让程序随便分配给用户一个数。 再导入java.util包下的Scanner类&#xff0c;构建Scanner对象&#xff0c;以便输入。 利用Random().nextInt()生成一个随机的i…

统计学中关于自由度的详细解释以及求平均值为什么消耗自由度1

首先我们要了解自由度是什么 自由度在本科教学中一般都不会过度涉及&#xff0c;因为它给老师和学生都带来了很大的困扰&#xff0c;它本身也有一些历史遗留问题&#xff0c;有很多人给出了很多不同的出发点和解释&#xff0c;比如1946年“自由度就是二次型的秩”&#xff0c;…

Android入门第42天-Android中的Service(IntentService)

开篇 在前一篇中我们讲了bindService的使用。并且我们留下了一个念想&#xff0c;即在bindService取值时故意阻塞30秒&#xff0c;引起了一次ANR并引出了今天的章节-IntentService。 IntentService的生命周期中有一个非常好的方法-onHandleIntent方法&#xff0c;它是一个abs…

创建你的第⼀个XXL-Job分布式调度任务

文章目录一、程序讲解1. 注解介绍2. 编写代码二、执⾏器管理2.1. Appname2.2. 名称2.3. 注册⽅式2.4. 机器地址2.5. 效果图三、任务管理一、程序讲解 1. 注解介绍 在 Spring Bean 实例中&#xff0c;开发 Job ⽅法⽅式格式要求为 public ReturnT<String> execute(Stri…

ARM 重定位引入和链接脚本

一、一个事实&#xff1a;大部分指令是位置有关编码 位置无关编码(PIC&#xff0c;position independent code)&#xff1a;汇编源文件被编码成二进制可执行程序时&#xff0c;编码方式与位置&#xff08;内存地址&#xff09;无关。 位置有关编码&#xff1a;汇编源码编码成…

分布式智能家居项目雏形

需求分析 客户端进入室内后(局域网)能够主动发现服务(如: 环境服务&#xff0c;灯光服务) 各种服务可以有不同的载体(如&#xff1a;由不同设备提供) 各种服务之间&#xff0c;服务与客户端之间完全无耦合(服务可自由增减) 客户端可以是移动APP&#xff0c;也可以是桌面软件…

【计算机毕业设计】基于JSP的房产中介系统的设计与实现

分类号&#xff1a;TP315 U D C&#xff1a;D10621-408-(2007) 6032 -0 密 级&#xff1a;公 开 编 号&#xff1a;2003211030 学位论文 基于JSP的房产中介系统的设计与实现 摘要 计算机与通信技术为基础的信息系统正处于蓬勃发展的时期。随着科学技术的不断提高&#xff…

2022SDNU-ACM结训赛题解

首先感谢一下各位出题人的精心准备、验题人的辛勤付出、以及选手的积极参加 题解 Problem A 柳予欣的归来【数学】 出题人&#xff1a; bhq 没想到一血是被打完山大的牛客比赛后来结训赛玩的wyx拿走的&#xff01; 题目描述&#xff1a; 计算(∑0<d<pd−1)m(\sum_{0…

Procreate iPad绘画教程

Procreate iPad绘画教程 通过动手绘画课程了解您需要了解的有关 Procreate 的所有信息。现在为 Procreate 5 更新 课程英文名&#xff1a;Drawing and Painting on the iPad with Procreate 此视频教程共11.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#x…

Qt第二十八章:异步

所有的数据处理都应该通过异步进行 定义信号# 自定义信号源 class QCustomSignal(QObject):signal_update_table Signal(list)signal_get_token Signal(str)signal_send_mq Signal() 处理函数 Slot()def handle_search(self):def thread_function():user_info get_use…

uImage的制作工具mkimage详解(源码编译、使用方法、添加的头解析、uImage的制作)

1、mkimage工具的源码 (1)mkimage是uboot下面的一个工具&#xff0c;用来将zImage制作成uImage&#xff0c;制作内核启动镜像(给zImage镜像添加64字节的头信息成uImage)&#xff1b; (2)mkimage的源码在"uboot/tool"目录下&#xff0c;在编译uboot时默认会编译出mkim…

假设检验(2)参数的假设检验

下面我们分情况讨论参数的假设检验问题&#xff0e; 3.2. 1 一个正态总体均值的检验&#xff08;方差已知时&#xff09; 例3.2. 1 某车间生产铜丝&#xff0c;铜丝的主要质量指标是折断力&#xff0c;根据过去的经验知该车间生产的铜丝折断力江今换了一批质量较好的原材料&am…

手把手实例教你短视频定位,人设和变现方式,学会节省半年摸索时间

手把手实例教你短视频定位,人设和变现方式,学会节省半年摸索时间 昨天在我赢助手的公开课上分享了一个变现模型&#xff0c;不光是做短视频可以用&#xff0c;在所有互联网项目都可以用。 基础概念就是单价、客户数量和时间的关系。 举个例子&#xff1a; 你的目标是一年赚1…

数据结构:二叉树的链式结构

文章目录一.前言二.二叉树遍历2.1前序遍历/先根遍历2.2中序遍历/中根遍历2.3后序遍历/后根遍历2.4层序遍历2.5二叉树的销毁三.二叉树节点个数四.二叉树叶子节点的个数五.二叉树的高度六.二叉树第K层的节点个数七.找二叉树的节点八.题目8.1判断单值二叉树8.2相同的树8.3另一棵子…

[Redis-实战] 企业常用的缓存使用方案(查询、更新、击穿、穿透、雪崩) 附源码

目录 &#x1f34a; 缓存查询策略 &#x1f369; 缓存更新策略 &#x1f36d; 缓存穿透 &#x1f363; 缓存雪崩 &#x1f355; 缓存击穿 &#x1f47e; 项目源码下载​​​​​​​ &#x1f34a; 缓存查询策略 我们要查询的业务数据并不是经常改变的, 这里我们可以放到Redis…