Java-SpringAop 编程式事物实现

SpringAop 编程式事物实现

1. 数据库事物特性
  • 原子性

多个数据库操作是不可分割的,只有所有的操作都执行成功,事物才能被提交;只要有一个操作执行失败,那么所有的操作都要回滚,数据库状态必须回复到操作之前的状态

  • 一致性

事物操作成功后,数据库的状态和业务规则必须一致。例如:从A账户转账100元到B账户,无论数据库操作成功失败,A和B两个账户的存款总额是不变的。

  • 隔离性

当并发操作时,不同的数据库事物之间不会相互干扰(当然这个事物隔离级别也是有关系的)

  • 持久性

事物提交成功之后,事物中的所有数据都必须持久化到数据库中。即使事物提交之后数据库立刻崩溃,也需要保证数据能能够被恢复。

2.事物隔离级别

当数据库并发操作时,可能会引起脏读、不可重复读、幻读、第一类丢失更新、第二类更新丢失等现象。

  • 脏读

事物A读取事物B尚未提交的更改数据,并做了修改;此时如果事物B回滚,那么事物A读取到的数据是无效的,此时就发生了脏读。

  • 不可重复读

一个事务执行相同的查询两次或两次以上,每次都得到不同的数据。如:A事物下查询账户余额,此时恰巧B事物给账户里转账100元,A事物再次查询账户余额,那么A事物的两次查询结果是不一致的。

  • 幻读

A事物读取B事物提交的新增数据,此时A事物将出现幻读现象。幻读与不可重复读容易混淆,如何区分呢?幻读是读取到了其他事物提交的新数据,不可重复读是读取到了已经提交事物的更改数据(修改或删除)

  • 第一类丢失更新

A事物的回滚覆盖了B事物已经提交的数据。如:账户有1000元,A事物执行取款100元操作,但未提交事物;此时B事物向账户存入100元并提交事物,账户余额改为1100元。此时A事物回滚了取款操作,账户余额被恢复成了1000元。

  • 第二类更新丢失

A事物的提交覆盖了B事物已经提交的数据。如:账户有1000元,A事物操作向账户存入100元,但未提交事物;此时B事物从账户取出100元并提交事物,账户余额改为900元;此时A事物提交事物,账户余额变为1100元。

对于以上问题,可以有多个解决方案,设置数据库事物隔离级别就是其中的一种,数据库事物隔离级别分为四个等级,通过一个表格描述其作用。

隔离级别脏读不可重复读幻象读第一类丢失更新第二类丢失更新
READ UNCOMMITTED允许允许允许允许允许
READ COMMITTED脏读允许允许允许允许
REPEATABLE READ不允许不允许允许不允许不允许
SERIALIZABLE不允许不允许不允许不允许不允许
3.Spring事物支持核心接口

在这里插入图片描述

TransactionDefinition–>定义与spring兼容的事务属性的接口

public interface TransactionDefinition {// 如果当前没有事物,则新建一个事物;如果已经存在一个事物,则加入到这个事物中。int PROPAGATION_REQUIRED = 0;// 支持当前事物,如果当前没有事物,则以非事物方式执行。int PROPAGATION_SUPPORTS = 1;// 使用当前事物,如果当前没有事物,则抛出异常。int PROPAGATION_MANDATORY = 2;// 新建事物,如果当前已经存在事物,则挂起当前事物。int PROPAGATION_REQUIRES_NEW = 3;// 以非事物方式执行,如果当前存在事物,则挂起当前事物。int PROPAGATION_NOT_SUPPORTED = 4;// 以非事物方式执行,如果当前存在事物,则抛出异常。int PROPAGATION_NEVER = 5;// 如果当前存在事物,则在嵌套事物内执行;如果当前没有事物,则与PROPAGATION_REQUIRED传播特性相同int PROPAGATION_NESTED = 6;// 使用后端数据库默认的隔离级别。int ISOLATION_DEFAULT = -1;// READ_UNCOMMITTED 隔离级别int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;// READ_COMMITTED 隔离级别int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;// REPEATABLE_READ 隔离级别int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;// SERIALIZABLE 隔离级别int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;// 默认超时时间int TIMEOUT_DEFAULT = -1;// 获取事物传播特性int getPropagationBehavior();// 获取事物隔离级别int getIsolationLevel();// 获取事物超时时间int getTimeout();// 判断事物是否可读boolean isReadOnly();// 获取事物名称@NullableString getName();
}
  1. Spring事物传播特性表:
传播特性名称说明
PROPAGATION_REQUIRED如果当前没有事物,则新建一个事物;如果已经存在一个事物,则加入到这个事物中
PROPAGATION_SUPPORTS支持当前事物,如果当前没有事物,则以非事物方式执行
PROPAGATION_MANDATORY使用当前事物,如果当前没有事物,则抛出异常
PROPAGATION_REQUIRES_NEW新建事物,如果当前已经存在事物,则挂起当前事物
PROPAGATION_NOT_SUPPORTED以非事物方式执行,如果当前存在事物,则挂起当前事物
PROPAGATION_NEVER以非事物方式执行,如果当前存在事物,则抛出异常
PROPAGATION_NESTED如果当前存在事物,则在嵌套事物内执行;如果当前没有事物,则与PROPAGATION_REQUIRED传播特性相同
  1. Spring事物隔离级别表:
隔离级别脏读不可重复读幻象读第一类丢失更新第二类丢失更新
ISOLATION_DEFAULT同后端数据库同后端数据库同后端数据库同后端数据库同后端数据库
ISOLATION_READ_UNCOMMITTED允许允许允许允许允许
ISOLATION_READ_COMMITTED脏读允许允许允许允许
ISOLATION_REPEATABLE_READ不允许不允许允许不允许不允许
ISOLATION_SERIALIZABLE不允许不允许不允许不允许不允许
  • PlatformTransactionManager–>Spring事务基础结构中的中心接口
public interface PlatformTransactionManager {// 根据指定的传播行为,返回当前活动的事务或创建新事务。TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;// 就给定事务的状态提交给定事务。void commit(TransactionStatus status) throws TransactionException;// 执行给定事务的回滚。void rollback(TransactionStatus status) throws TransactionException;
}

Spring将事物管理委托给底层的持久化框架来完成,因此,Spring为不同的持久化框架提供了不同的PlatformTransactionManager接口实现。列举几个Spring自带的事物管理器:

事物管理器说明
org.springframework.jdbc.datasource.DataSourceTransactionManager提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事务管理
org.springframework.orm.jpa.JpaTransactionManager提供对单个javax.persistence.EntityManagerFactory事务支持,用于集成JPA实现框架时的事务管理
org.springframework.transaction.jta.JtaTransactionManager提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器
  • TransactionStatus–>事物状态描述
  1. TransactionStatus接口
public interface TransactionStatus extends SavepointManager, Flushable {// 返回当前事务是否为新事务(否则将参与到现有事务中,或者可能一开始就不在实际事务中运行)boolean isNewTransaction();// 返回该事务是否在内部携带保存点,也就是说,已经创建为基于保存点的嵌套事务。boolean hasSavepoint();// 设置事务仅回滚。void setRollbackOnly();// 返回事务是否已标记为仅回滚boolean isRollbackOnly();// 将会话刷新到数据存储区@Overridevoid flush();// 返回事物是否已经完成,无论提交或者回滚。boolean isCompleted();
}
  1. SavepointManager接口
public interface SavepointManager {// 创建一个新的保存点。Object createSavepoint() throws TransactionException;// 回滚到给定的保存点。// 注意:调用此方法回滚到给定的保存点之后,不会自动释放保存点,// 可以通过调用releaseSavepoint方法释放保存点。void rollbackToSavepoint(Object savepoint) throws TransactionException;// 显式释放给定的保存点。(大多数事务管理器将在事务完成时自动释放保存点)void releaseSavepoint(Object savepoint) throws TransactionException;
}
  1. Flushable接口
public interface Flushable {// 将会话刷新到数据存储区void flush() throws IOException;
}

4.Spring编程式事物

CREATE TABLE `account` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',`balance` int(11) DEFAULT NULL COMMENT '账户余额',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='--账户表'

实现

package com.lyc.cn.v2.day08;import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;import javax.sql.DataSource;/*** Spring编程式事物* @author: LiYanChao* @create: 2018-11-09 11:41*/
public class MyTransaction {private JdbcTemplate jdbcTemplate;private DataSourceTransactionManager txManager;private DefaultTransactionDefinition txDefinition;private String insert_sql = "insert into account (balance) values ('100')";public void save() {// 1、初始化jdbcTemplateDataSource dataSource = getDataSource();jdbcTemplate = new JdbcTemplate(dataSource);// 2、创建物管理器txManager = new DataSourceTransactionManager();txManager.setDataSource(dataSource);// 3、定义事物属性txDefinition = new DefaultTransactionDefinition();txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// 3、开启事物TransactionStatus txStatus = txManager.getTransaction(txDefinition);// 4、执行业务逻辑try {jdbcTemplate.execute(insert_sql);//int i = 1/0;jdbcTemplate.execute(insert_sql);txManager.commit(txStatus);} catch (DataAccessException e) {txManager.rollback(txStatus);e.printStackTrace();}}public DataSource getDataSource() {BasicDataSource dataSource = new BasicDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/my_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8");dataSource.setUsername("root");dataSource.setPassword("liyanchao1989@");return dataSource;}}
  • 增加Gradle模块和包
// 引入spring-jdbc模块
optional(project(":spring-jdbc"))// https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'// https://mvnrepository.com/artifact/mysql/mysql-connector-java
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.38'
  • 测试类及结果
package com.lyc.cn.v2.day08;import org.junit.Test;/*** @author: LiYanChao* @create: 2018-11-07 18:45*/
public class MyTest {@Testpublic void test1() {MyTransaction myTransaction = new MyTransaction();myTransaction.save();}
}

运行测试类,在抛出异常之后手动回滚事物,所以数据库表中不会增加记录。

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

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

相关文章

redis-操作数据库

0 序言 一个Redis服务器可以包含多个数据库。在默认情况下,Redis服务器在启动时将会创建16个数据库:这些数据库都使用号码进行标识,其中第一个数据库为0号数据库,第二个数据库为1号数据库,而第三个数据库则为2号数据库…

每日五道java面试题之mybatis篇(一)

目录: 第一题. MyBatis是什么?第二题. ORM是什么?第三题. 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?第四题. 传统JDBC开发存在的问题第五题. JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的…

计算机考研|北航北理北邮怎么选?

北航985,北理985,北邮211 虽然北邮事211,但是北邮的计算机实力一点也不弱,学科评级,计算机是A 北航计算机评级也是A,北理的计算机评级是A- 所以,这三所学校在实力上来说,真的大差…

LeetCode 面试经典150题 274.H指数

题目: 给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她…

DM数据库安装(Linux)

Linux安装 操作系统CPU数据库CentOS7x86_64 架构dm8_20230418_x86_rh6_64 先把压缩包扔过去 新建 dmdba 用户 创建用户所在的组,命令如下: groupadd dinstall 创建用户,命令如下: useradd -g dinstall -m -d /home/dmdba -s /…

由浅到深认识C语言(13):共用体

该文章Github地址:https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn…

ConKI: Contrastive Knowledge Injection for Multimodal Sentiment Analysis

文章目录 ConKI:用于多模态情感分析的对比知识注入文章信息研究目的研究内容研究方法1.总体结构2.Encoding with Knowledge Injection2.1 Pan-knowledge representations2.2 Knowledge-specific representations 3.Hierarchical Contrastive Learning4.损失函数5.训…

信息检索(十四):Simple Entity-Centric Questions Challenge Dense Retrievers

Simple Entity-Centric Questions Challenge Dense Retrievers 摘要1. 引言2. 背景和相关工作3. EntityQuestions4. 剖析问题:实体 vs 问题模式4.1 密集检索表现出流行偏差4.2 观察问题有助于泛化 5. 迈向稳健的密集检索6. 结论 原文链接:https://aclant…

一文教会你SpringBoot是如何启动的

SpringBoot启动流程分析 流程图 源码剖析 运行Application.run()方法 我们在创建好一个 SpringBoot 程序之后,肯定会包含一个类:xxxApplication,我们也是通过这个类来启动我们的程序的(梦开始的地方),而…

【趣味项目】命令行图片格式转换器

【趣味项目】一键生成LICENSE 项目地址:GitHub 项目介绍 一款命令行内可以批量修改图片格式的工具 使用方式 npm install xxhls/image-transformer -gimg-t --name.*.tiff --targetpng --path./images --recursiontrue技术选型 typeScript: 支持类型体操chal…

【网络安全】 MSF生成木马教程

本文章仅用于信息安全学习,请遵守相关法律法规,严禁用于非法途径。若读者因此作出任何危害网络安全的行为,后果自负,与作者无关。 环境准备: 名称系统位数IP攻击机Kali Linux6410.3.0.231客户端Windows 76410.3.0.234…

Python中的迭代器与生成器提高性能的秘密武器【第143篇—迭代器与生成器】

👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Python中的迭代器与生成器:提高性能的秘密武器 在Python编程中,迭代…

[TJOI2010] 阅读理解 **STL**Tire树**

[TJOI2010] 阅读理解 题目链接: https://www.luogu.com.cn/problem/P3879 题目描述 思路1 (STL大法) 对每个单词,用map来映射存储它所在的短文编号 用set的好处: -------1. 存储直接自动排序,操作简单&…

【开源】SpringBoot框架开发毕业生追踪系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登陆注册模块2.2 学生基本配置模块2.3 就业状况模块2.4 学历深造模块2.5 信息汇总分析模块2.6 校友论坛模块 三、系统设计3.1 用例设计3.2 实体设计 四、系统展示五、核心代码5.1 查询我的就业状况5.2 初始化就业状况5.…

单链表OJ题

单链表OJ题(文字解读 图解) 1. 移除链表元素2. 反转链表3. 链表的中间结点4. 返回倒数第 k 个节点5. 合并两个有序链表 1. 移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点&#xff…

第六节:使用SMB开发WebService

一、概述 webservice在日常开发中是常用的接口形式,SMB在设计之初就将webservice作为重要的代理协议。在组件库中提供了webservice input和webservice output两个组件,分别用于发布接口和调用接口。 二、发布webservice 在csdnProject工程中创建名为c…

【设计模式】-工厂模式

工厂模式是一种创建型设计模式,它提供了一种在不指定具体类的情况下创建对象的方法。工厂模式的核心思想是将对象的创建与使用分离,降低系统的耦合度,使系统更加灵活、可扩展。 工厂模式主要分为三种类型:简单工厂模式、工厂方法…

#Ubuntu(修改root信息)

(一)发行版:Ubuntu16.04.7 (二)记录: (1)命令行终端: a.右键,open terminal b.快捷键 ctrlaltt (2)进行root修改 sudo passwd &a…

【推荐系统】NCF神经协同过滤

NCF框架 NCF框架是本文要实现的3个模型的主体结构。 首先是输入层,分别包含两个特征向量 v u v_u vu​和 v i v_i vi​,描述了用户u和物品i。输入仅由一个用户向量和一个物品向量构成,它们分别是以one-hot编码的二值化稀疏向量。 接着是Em…

[HNCTF 2022 WEEK2]e@sy_flower

获取基本信息 获取关键字符串 进来“开门红” 上一篇博客才发现这个 按u转换为二进制 有个无效db,最简单的花指令 nop掉 重新u一下p一下 就正常了 然后编译完main函数 int __cdecl __noreturn main(int argc, const char **argv, const char **envp) {signed in…