Spring声明式事务控制

文章目录

  • 1.编程式事务控制相关对象(了解即可)
    • 1.1PlarformTransactionManager
    • 1.2 TransactionDefinition
  • 2.基于XML的声明式事务控制
    • 2.1声明式事务控制的实现
  • 3.基于注解的声明式事务控制

1.编程式事务控制相关对象(了解即可)

1.1PlarformTransactionManager

PlatformTransactionManager 接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法。
在这里插入图片描述
注意:PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类,例如:Dao 层技术是jdbc 或 mybatis 时:org.springframework.jdbc.datasource.DataSourceTransactionManager
Dao 层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager

1.2 TransactionDefinition

TransactionDefinition 是事务的定义信息对象,里面有如下方法:
在这里插入图片描述

  1. 事务隔离级别:
    设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读:
  • ISOLATION_DEFAULT
  • ISOLATION_READ_UNCOMMITTED
  • ISOLATION_READ_COMMITTED
  • ISOLATION_REPEATABLE_READ
  • ISOLATION_SERIALIZABLE
脏读幻读不可重复度
READ_UNCOMMITTED(读未提交)
READ_COMMITTED(读已提交)×
REPEATABLE_READ(可重复读)××
SERIALIZABLE(串行化)×××
  1. 事务传播行为
  • REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
  • MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
  • REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
  • NEVER:以非事务方式运行,如果当前存在事务,抛出异常
  • NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
  • 超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
  • 是否只读:建议查询时设置为只读
  1. TransactionStatus
    TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下:
    在这里插入图片描述

2.基于XML的声明式事务控制

Spring 的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明,用在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。声明式事务处理的作用:

  • 事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可
  • 在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便

通过账户转账的案例学习声明式事务,先书写基础源码,利用maven新建一个项目:

  • 在pom.xml加入项目依赖:
  <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.4</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-test --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.5.RELEASE</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2.1</version></dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.23</version></dependency></dependencies>
  • 编写domain、Dao、Service层的代码:
    domain - Account.java
package com.zhxd.domain;public class Account {private String name;private double money;public String getName() {return name;}public void setName(String name) {this.name = name;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"name='" + name + '\'' +", money=" + money +'}';}
}

Dao - AccountDaoImpl.java

package com.zhxd.dao;interface AccountDao {//转出void out(String outMan, double money);//转入void in(String inMan, double money);
}public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic void out(String outMan, double money) {jdbcTemplate.update("update account set money=money-? where name=?", money, outMan);}@Overridepublic void in(String inMan, double money) {jdbcTemplate.update("update account set money=money+? where name=?", money, inMan);}
}

Service - AccountServiceImpl.java

interface AccountService {//转账void transfer(String outMan, String inMan, double money);
}public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}@Overridepublic void transfer(String outMan, String inMan, double money) {accountDao.out(outMan, money);accountDao.in(inMan, money);}
}
  • 在数据库新建Account数据表:
    在这里插入图片描述
  • 在Spring配置文件配置Bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--配置数据源--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/test"></property><property name="user" value="root"></property><property name="password" value="root"></property></bean><!--配置JdbcTemplate--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!--配置AccountDao--><bean id="accountDao" class="com.zhxd.dao.impl.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><!--配置AccountService--><bean id="accountService" class="com.zhxd.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"></property></bean>
</beans>

2.1声明式事务控制的实现

  1. 引入tx和aop的命名空间:
    在这里插入图片描述
  2. 配置事务增强:
<!--配置事务平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property> <!--配置数据源获取connection-->
</bean><!--事务增强配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*"/></tx:attributes>
</tx:advice>

其中,<tx:method> 代表切点方法的事务参数的配置,例如:<tx:method name=“transfer” isolation=“REPEATABLE_READ” propagation=“REQUIRED” timeout=“-1” read-only=“false”/

  • name:切点方法名称
  • isolation:事务的隔离级别
  • propogation:事务的传播行为
  • timeout:超时时间
  • read-only:是否只读
  1. 配置事务 AOP 织入
    <!--配置事务织入--><aop:config><aop:advisor advice-ref="txAdvice" pointcut="execution(* com.zhxd..*(..))"></aop:advisor></aop:config>
  1. 测试事务控制转账业务代码,程序故意抛出java.lang.ArithmeticException: / by zero异常:
 public void transfer(String outMan, String inMan, double money) {accountDao.out(outMan, money);int a = 2/0;//异常accountDao.in(inMan, money);}

查看数据库转账结果:
在这里插入图片描述
没有转账成功,还是原来的数据,把织入关系注释之后再查看结果:

<!--配置事务平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property> <!--配置数据源获取connection-->
</bean><!--事务增强配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="transfer" isolation="SERIALIZABLE" propagation="REQUIRED" timeout="-1" read-only="false"/></tx:attributes>
</tx:advice><!--配置事务织入-->
<!--<aop:config><aop:advisor advice-ref="txAdvice" pointcut="execution(* com.zhxd..*(..))"></aop:advisor>
</aop:config>-->

在这里插入图片描述

3.基于注解的声明式事务控制

  1. 使用注释的方式注入Dao和Service
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic void out(String outMan, double money) {jdbcTemplate.update("update account set money=money-? where name=?", money, outMan);}@Overridepublic void in(String inMan, double money) {jdbcTemplate.update("update account set money=money+? where name=?", money, inMan);}
}@Service("accountService")
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Overridepublic void transfer(String outMan, String inMan, double money) {accountDao.out(outMan, money);accountDao.in(inMan, money);}
}
  1. 修改applicationContext.xml
 <!--配置包扫描--><context:component-scan base-package="com.zhxd" /><!--引入事务注解驱动--><tx:annotation-driven />
  1. 在切点方法或者切点所在类上面加入@Transactional:
  • 如果把这个注解添加类上面,这个类里面所有的方法都添加事务
  • 如果把这个注解添加方法上面,为这个方法添加事务
    @Transactional有一下属性:
    在这里插入图片描述
package com.zhxd.service.impl;import com.zhxd.dao.AccountDao;
import com.zhxd.domain.Account;
import com.zhxd.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Service("accountService")
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Override@Transactional(isolation = Isolation.READ_COMMITTED,propagation =Propagation.REQUIRED)public void transfer(String outMan, String inMan, double money) {accountDao.out(outMan, money);accountDao.in(inMan, money);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【信号处理】心电信号传统R波检测定位典型方法实现(matlab)

关于 心电信号中QRS波检测是一个非常重要的步骤&#xff0c;可以用于实现重要波群的基本定位&#xff0c;在定位基础上&#xff0c;可以进一步分析心电信号的特征变化&#xff0c;从而为医疗诊断提供必要的参考。 工具 MATLAB ECG心电信号 方法实现 ECG心电信号加载 ecg …

基于Python豆瓣电影数据可视化分析系统的设计与实现

大数据可视化项目——基于Python豆瓣电影数据可视化分析系统的设计与实现 2024最新项目 项目介绍 本项目旨在通过对豆瓣电影数据进行综合分析与可视化展示&#xff0c;构建一个基于Python的大数据可视化系统。通过数据爬取收集、清洗、分析豆瓣电影数据&#xff0c;我们提供了…

机器学习-随机森林温度预测模型优化

文章目录 前言旧模型训练新模型训练参数查看组合参数训练学习模型评估 前言 在机器学习-随机森林算法预测温度一文中&#xff0c;通过增大模型训练数据集和训练特征的方式去优化模型的性能&#xff0c;本文将记录第三方种优化方式&#xff0c;通过调整随机森林创建模型参数的方…

如何安装MacOS的虚拟机?mac安装虚拟机的步骤 虚拟机安装MacOS VMware Fusion和Parallels Desktop19

要在Mac上运行MacOS的虚拟机&#xff0c;常用的方法是使用虚拟化软件如VMware Fusion或Parallels Desktop。 以下是安装MacOS的虚拟机的主要步骤&#xff1a; 1. 检查系统要求&#xff1a;确定您的Mac硬件和操作系统满足安装要求。您需要一台具备足够性能的Mac&#xff0c;并…

Lua脚本使用手册(Redis篇)

Lua脚本 **简介&#xff1a;**Lua是一种功能强大的&#xff0c;高效&#xff0c;轻量级&#xff0c;可嵌入的脚本语言。它是动态类型语言&#xff0c;通过使用基于寄存器的虚拟机解释字节码运行&#xff0c;并具有增量垃圾收集的自动内存管理&#xff0c;是配置&#xff0c;脚…

ASP.NET基于BS的计算机等级考试系统的设计与实现

摘 要 随着计算机技术的发展及计算机的日益普及&#xff0c;基于B/S结构的考试系统与无纸化办公一样已成为大势所趋。论文详细论述了一个基于B/S结构的计算机等级考试系统的设计过程。软件采用ASP.NET 2005作开发平台&#xff0c;C#作编程语言&#xff0c;SQL Server 2005作…

Python进阶编程 --- 2.MySQL、pymysql、PySpark

文章目录 第一章&#xff1a;SQL基础入门1.1 数据库数据库如何存储数据 1.2 数据库和SQL的关系1.3 MySQL版本1.4 命令提示符内使用MySQL1.5 SQL概述1.5.1 SQL语言分类1.5.2 SQL语言特性 1.6 DDL库管理表管理 1.7 DML - 数据操作1.8 DQL - 查询和计算数据1.8.1 基础数据查询1.8.…

《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制空气质量数据平行坐标图

在MATLAB中绘制平行坐标图可以使用parallelcoords函数。平行坐标图通常用于可视化多维数据&#xff0c;特别适用于观察各个维度之间的关系。以下是一个简单的示例&#xff0c;展示如何使用MATLAB创建一个平行坐标图。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/dire…

爬虫 | 网易新闻热点数据的获取与保存

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目是一个简单的网络爬虫&#xff0c;用于从网易新闻的热点新闻列表中提取标题和对应的链接&#xff0c;并将提取到的数据保存到一个 CSV 文件中。 目录 一、技术栈 二、功能说明 三、注意事项 四、代码解析 1. 导入所需…

Python 全栈 Web 应用模板:成熟架构,急速开发 | 开源日报 No.223

tiangolo/full-stack-fastapi-template Stars: 15.6k License: MIT full-stack-fastapi-template 是一个现代化的全栈 Web 应用模板。 使用 FastAPI 构建 Python 后端 API。使用 SQLModel 进行 Python SQL 数据库交互&#xff08;ORM&#xff09;。Pydantic 用于数据验证和设…

Redis入门到通关之List命令

文章目录 ⛄介绍⛄List的常见命令有⛄RedisTemplate API❄️❄️添加缓存❄️❄️将List放入缓存❄️❄️设置过期时间(单独设置)❄️❄️获取List缓存全部内容&#xff08;起始索引&#xff0c;结束索引&#xff09;❄️❄️从左或从右弹出一个元素❄️❄️根据索引查询元素❄…