Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >8-Spring事务控制

8-Spring事务控制

作者头像
Ywrby
发布于 2022-10-27 05:25:14
发布于 2022-10-27 05:25:14
31000
代码可运行
举报
文章被收录于专栏:YwrbyYwrby
运行总次数:0
代码可运行

Spring事务控制

事务概念

概括来讲,事务是一个由有限操作集合组成的逻辑单元。事务操作包含两个目的,数据一致以及操作隔离。数据一致是指事务提交时保证事务内的所有操作都成功完成,并且更改永久生效;事务回滚时,保证能够恢复到事务执行之前的状态。操作隔离则是指多个同时执行的事务之间应该相互独立,互不影响。

事务是一个比较广泛的概念,事务管理资源除了我们熟知的数据库外,还可以包含消息队列文件系统等。当然,一般来说,我们说的事务单指“数据库事务”。

事务的ACID属性

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

编程式事务控制

Spring编程式事务控制就是指利用Spring提供的API进行事务控制,通过编写Java代码的方式完成,这种事务控制方法相对较灵活,但不便于管理,即耦合度较高

PlatformTransactionManager 平台事务管理器

PlatformTransactionManager接口是Spring的事务管理器类,内部提供了我们常用的操作事务的方法

方法

说明

TransactionStatus getTransaction(TransactionDefination defination)

获取事务状态信息

void commit(TransactionStatus status)

获取事务状态信息

void rollback(TransactionStatus status)

回滚事务

根据dao层的不同技术实现(例如JDBC或mybatis…),PlatformTransactionManager接口实现了不同的实现类

TransactionDefination

TransactionDefination是事务的定义信息对象,实现了如下方法

方法

说明

int getIsolationLevel()

获得事务的隔离级别

int getPropogationBehavior()

获得事务的传播行为

int getTimeout()

获得超时时间

boolean isReadyOnly()

是否只读

事务的隔离级别

设置事务级别,用于解决事务并发产生的问题。如脏读,不可重复度,虚读…

  • ISOLATION_DEFAULT:默认隔离级别
  • ISOLATION_READ_UNCOMMITTED:读未提交
  • ISOLATION_READ_COMMITTED:读已提交(可以解决脏读)
  • ISOLATION_REPEATABLE_READ:可重复读(可以解决不可重复读问题)
  • ISOLATION_SERIALIZABLE:串行化(都可以解决 但效率低下)
事务的传播行为

事务传播行为用于描述当一个事务传播行为的修饰方法其他方法调用时,事务是如何传播的

Spring中提供了其中事务传播的行为

事务传播行为

说明

REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)

SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)

MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常

REQUERS_NEW

新建事务,如果当前在事务中,把当前事务挂起。

NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

NEVER

以非事务方式运行,如果当前存在事务,抛出异常

NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作

  • 超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
  • 是否只读:建议查询时设置为只读

TransactionStatus

TransactionStatus接口提供了事务具体的运行状态

方法

说明

boolean hasSavepoint()

是否存储回滚点

boolean isCompleted()

事务是否完成

boolean isNewTransaction()

是否是新事务

boolean isRollBackOnly()

事务是否回滚

Spring声明式事务控制

Spring的声明式事务控制就是指利用声明的方式进行事务控制,这里所指的声明就是利用Spring配置文件或注解的方式进行配置

声明式事务控制的作用

事务管理是属于系统层面的服务,而我们所编写的业务逻辑对象是属于业务逻辑层面的,如果使用编程式事务控制,就需要将事务管理和业务逻辑对象一起进行编写,二者将被耦合死。二通过声明式事务控制,则可以通过配置的方式,在配置文件中编写如何利用业务逻辑对象进行事务管理,此时业务逻辑对象并不会意识到自己正在执行相关事务,即实现了解耦合(业务逻辑与事务管理之间)

这个过程实际上还是遵循了Spring中的AOP,整个过程是为了实现对方法的增强,而增强的方式就是通过使用事务,即业务逻辑对象是切点,事务是通知(增强)

Spring声明式事务控制的底层就是AOP

基于XML方式的声明式事务控制

以银行转账事务为例进行基于XML方式的声明式事务控制

dao层:定义数据库操作方法

in方法为修改入帐方的余额

out方法为修改出账方发余额

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface AccountDao {
    public void in(String inMan,double money);
    public void out(String outMan,double money);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public void in(String inMan, double money) {
        jdbcTemplate.update("update account set money=money+? where name =?",money,inMan);
    }

    public void out(String outMan, double money) {
        jdbcTemplate.update("update account set money=money-? where name =?",money,outMan);
    }
}

Service层

transfer方法就是转账方法,接收出账方,入帐方和金额三个参数

transfer方法调用了in方法和out方法,这两个方法各自为一个事务,此时如果不进行事务控制,可以看到由于二者之间故意设置的除数错误,会导致入账事务执行并完成,但出账事务未进行。

因此必须通过事务控制增强这个方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface AccountService {
    public void transfer(String outMan,String inMan,double money);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component("accountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDaoImpl accountDao;

    public void setAccountDao(AccountDaoImpl accountDao) {
        this.accountDao = accountDao;
    }

    public void transfer(String outMan, String inMan, double money) {
        accountDao.in(inMan,money);
        int i=1/0;
        accountDao.out(outMan,money);
    }
}

配置文件

首先要引入AOP命名空间用于进行事务的织入,其次还需要引入tx命名空间进行事务通知的定义

然后就是需要配置平台事务管理器并为其配置数据源以进行事务管理,并且要定义通知(在tx命名空间中)

最后进行织入,将通知织入指定方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<!--引入tx命名空间,用于进行事务的管理-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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
                           http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置注解扫描-->
    <context:component-scan base-package="cn.ywrby"/>

    <!--加载properties配置文件(classpath表示的就是资源目录resources下)-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}"></property>
        <property name="jdbcUrl" value="${url}"></property>
        <property name="user" value="${user}"></property>
        <property name="password" value="${password}"></property>
    </bean>

    <!--配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置平台事务管理器TransactionManager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--通知 用于进行事务的增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--设置事务的属性信息-->
        <tx:attributes>
            <!--name设置增强的方法 *表示所有方法均进行增强-->
            <!--isolation表示隔离级别-->
            <!--propagation表示事务的传播行为-->
            <!--timeout表示超过时间-->
            <!--read-only表示是否只读-->
            <tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" timeout="-1" read-only="false" />
        </tx:attributes>
    </tx:advice>

    <!--配置AOP事务的织入:将事务织入到业务逻辑对象的方法中-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.ywrby.service.impl.*.*(..))"></aop:advisor>
    </aop:config>
</beans>

基于注解的Spring事务控制

基于注解的Spring事务控制需要修改两处,首先在需要进行事务控制的方法或类上利用@Transactional注解表示对该方法进行事务控制,(其内可以传入参数进行属性的配置)

可以看到,类上和方法上都可以使用该注解,当在类上使用该注解时表示该类内所有方法均按此配置进行事务控制,同时若方法上另有配置,则遵循方法上的配置(就近原则)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component("accountService")
@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.MANDATORY,readOnly = false,timeout = -1)
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDaoImpl accountDao;

    public void setAccountDao(AccountDaoImpl accountDao) {
        this.accountDao = accountDao;
    }

    @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)
    public void transfer(String outMan, String inMan, double money) {
        accountDao.in(inMan,money);
        int i=1/0;
        accountDao.out(outMan,money);
    }
}

其次还需要修改配置文件,以进行事务的注解驱动声明

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<!--引入tx命名空间,用于进行事务的管理-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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
                           http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置注解扫描-->
    <context:component-scan base-package="cn.ywrby"/>

    <!--加载properties配置文件(classpath表示的就是资源目录resources下)-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}"></property>
        <property name="jdbcUrl" value="${url}"></property>
        <property name="user" value="${user}"></property>
        <property name="password" value="${password}"></property>
    </bean>

    <!--配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置平台事务管理器TransactionManager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--声明事务的注解驱动-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring声名式事务控制学习笔记
1、事务的基本要素(ACID) 原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做。 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
咕咕星
2020/12/23
3380
Spring的事务控制
第一:JavaEE 体系进行分层开发,事务处理位于业务层,Spring 提供了分层设计业务层的事务处理解决方案。 第二:spring 框架为我们提供了一组事务控制的接口。具体在后面的第二小节介绍。这组接口是在spring-tx-5.0.2.RELEASE.jar 中。 第三:spring 的事务控制都是基于 AOP 的,它既可以使用编程的方式实现,也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。
暴躁的程序猿
2022/03/23
3310
Spring系列之事务的控制 注解实现+xml实现+事务的隔离等级
在前面我写过一篇关于事务的文章,大家可以先去看看那一篇再看这一篇,学习起来会更加得心应手
一只胡说八道的猴子
2020/10/09
5340
Spring系列之事务的控制 注解实现+xml实现+事务的隔离等级
Spring事务管理
事务的特性: 原子性:事务不可分割 一致性:事务执行前后数据完整性保持一致 隔离性:一个事务的执行不应该受到其他事务的干扰 持久性:一旦事务结束,数据就持久到数据库
用户3112896
2019/09/26
4790
快速学习-Spring 中的事务控制
第一:JavaEE 体系进行分层开发,事务处理位于业务层,Spring 提供了分层设计业务层的事务处理解决方案。
cwl_java
2020/04/03
4740
快速学习-Spring 中的事务控制
Spring:JDBC Template,声明式事务
JdbcTemplate 是 spring 框架中提供的一个模板对象,是对原始繁琐的 JDBC API 对象的简单封装。
RendaZhang
2020/09/16
1.1K0
Spring:JDBC Template,声明式事务
Spring事务还能这样管理?
在该JAR包的org.springframework.transaction包中,有3个接口文件PlatformTransactionManager、TransactionDefinition和TransactionStatus
千羽
2021/12/29
2800
Spring事务还能这样管理?
Spring学习笔记(五)——JdbcTemplate和spring中声明式事务
它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。spring 框架为我们提供了很多的操作模板类。 1. 操作关系型数据的: JdbcTemplate HibernateTemplate 2. 操作 nosql 数据库的: RedisTemplate 3. 操作消息队列的: JmsTemplate spring中的JdbcTemplate在 spring-jdbc-5.0.2.RELEASE.jar 中,我们在导包的时候,除了要导入这个 jar 包外,还需要导入一个 spring-tx-5.0.2.RELEASE.jar(它是和事务相关的)。
不愿意做鱼的小鲸鱼
2022/09/24
8360
Spring学习笔记(五)——JdbcTemplate和spring中声明式事务
Spring 基于注解配置方式的声明事务控制(注解方式)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
多凡
2019/11/01
8380
SSH框架之Spring第四篇
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
海仔
2019/09/23
5260
Spring 基于 XML 的声明式事务控制(配置方式)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
多凡
2019/11/01
4660
[Spring框架]Spring 事务管理基础入门总结.
前言: 在之前的博客中已经说过了数据库的事务, 不过那里面更多的是说明事务的一些锁机制, 今天来说一下Spring管理事务的一些基础知识.  之前的文章: [数据库事务与锁]详解一: 彻底理解数据库事务 一, 什么是事务 事务是逻辑上一组操作,这组操作要么全都成功,要么全都失败. 事务的属性: ACID 原子性(Atomicity): 事务作为一个整体被执行,包含在其中的对数据的操作要么全部被执行,要么都不执行. 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态.
一枝花算不算浪漫
2018/05/18
7790
Spring详解(八)------事务管理
IT可乐
2018/01/04
8050
Spring详解(八)------事务管理
12 Spring框架 SpringDAO的事务管理
上一节我们说过Spring对DAO的两个支持分为两个知识点,一个是jdbc模板,另一个是事务管理。 事务是数据库中的概念,但是在一般情况下我们需要将事务提到业务层次,这样能够使得业务具有事务的特性,来管理业务。 例如:在银行的转账系统中,张三转账给李四,需要完成从张三的账户上扣取指定金额并加到李四的账户上,这样一个过程需要具有原子性,即要成功都成功,要失败都失败。转账的过程即两个对账户更新,需要将事务提升到业务层次,使得两个操作具有原子性! 对以上的实现,Spring的API中有两个常用的接口我们会使用
MindMrWang
2018/04/16
8050
12 Spring框架 SpringDAO的事务管理
学习Spring框架这一篇就够了
Spring是分层的 Java SE/EE应用 full-stack(全栈的) 轻量级开源框架,以 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
全栈程序员站长
2022/09/07
1.6K0
学习Spring框架这一篇就够了
Spring框架(V1.3)
SSM框架-Spring框架 spring提供了很多模板整合Dao技术 1.SpringTemplate 1.1.SpringTemplate概述 spring中提供了一个可以操作数据库的对象.对象封装了jdbc技术. JDBCTemplate => JDBC模板对象 与DBUtils中的QueryRunner非常相似. 1.2.入门案例 1.2.1.添加功能 User对象入参 步骤: 导入jar包 基本jar包 4+2 aop包 操作jdbc 数据库 总体jar包图 插
软件小生活
2021/10/20
3460
Spring5.0源码学习系列之事务管理概述
Spring5.0源码学习系列之事务管理概述(十一),在学习事务管理的源码之前,需要对事务的基本理论比较熟悉,所以本章节会对事务管理的基本理论进行描述
烂猪皮
2021/07/16
3120
Spring5.0源码学习系列之事务管理概述
JAVA后端面试《Spring》
概念:SPring是一个支持控制反转(IOC)和面向切面编程(AOP)的容器框架。 好处:两降低>>>两支持>>>两方便
后端码匠
2020/02/25
8000
Spring框架 Spring事务
1 、什么事务 ( 1 )事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操 作都失败 ( 2 )典型场景:银行转账
郭顺发
2023/07/07
2130
Spring事务管理[通俗易懂]
  TransactionDefinition:封装事务的隔离级别,超时时间,是否为只读事务和事务的传播规则等事务属性,可通过XML配置具体信息。
全栈程序员站长
2022/09/07
2940
相关推荐
Spring声名式事务控制学习笔记
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文