事务概念:

原子性:要么都成功,有一个失败都失败

一致性:总量不变(A有100元,B有100元,总量是200元。A把100元转给B,B就有了200元,总量还是200元)

隔离性:两人操作同一条数据,不会相互影响

持久性:最终提交到数据库后成功


搭建事务操作环境进行操作():

银行转账例子:

1.1、创建数据库,创建表,添加数据

create table t_account
(
id int auto_increment primary key,
username varchar(50) null,
money int null
);

1.2、在项目中创建Service,Dao 完成对象创建和注入

结构: 先配置bean配置文件,然后创建service创建dao。service里面注入dao,dao里面注入jdbc模板。在dao里面两个方法{多钱方法][少钱方法}。service中转账分别调用两个方法完成最终过程

配置xml:
<context:component-scan base-package="com.spring.test"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/user_db"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
dao层:
package com.spring.test.dao;

public interface UserDao {
//多钱的方法
public void addMoney();
//少钱的方法
public void reduceMoney();
}
实现类:
package com.spring.test.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository; @Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate; //多钱
@Override
public void addMoney() {
String sql = "update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"marry");
}
//少钱
@Override
public void reduceMoney() {
String sql = "update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
}

service层:
package com.spring.test.service;

import com.spring.test.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao; //转账操作
public void accountMoney(){
//lucy少100
userDao.reduceMoney();
//marry多100
userDao.addMoney();
}
}

测试文件:
package com.spring.test.run;

import com.spring.test.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class AppRun {
@Test
public void RunTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService = (UserService)context.getBean("userService");
userService.accountMoney();
}
}
执行结果:

数据执行成功~!

来继续查看数据库变化

上面的操作,如果正常执行是没有问题的,但是代码执行过程中出现一场,则转账会发生严重问题。

模拟异常环境:

service层中添加异常代码来模拟转账时的突然停电操作

package com.spring.test.service;

import com.spring.test.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao; //转账操作
public void accountMoney(){
//lucy少100
userDao.reduceMoney(); //异常代码
int a = 12/0; //marry多100
userDao.addMoney();
}
}

通过前面的测试结果lucy的钱是900元,marry的钱是1100元。

接下来进行异常测试

运行测试文件后抛出异常:

八月 03, 2020 9:22:46 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
//下面的是报错--可以认为转账过程中停电了,但是lucy已经转账了100元
java.lang.ArithmeticException: / by zero
at com.spring.test.service.UserService.accountMoney(UserService.java:19)
at com.spring.test.run.AppRun.RunTest(AppRun.java:13)

接着查看数据库内容

发现lucy的钱已经少了100,而marry并没有接收到转来的100元,这就是一个异常。

解决这个问题的方法:

(典型方法)

操作过程:1、开启事务操作 2、进行业务上的操作 3、没有发生异常,提交数据 4、如果出现异常,进行事务回滚

//转账操作
public void accountMoney(){
try {
//第一步 开启事务
//第二步 进行业务操作
//lucy少100
userDao.reduceMoney(); //会出异常的代码
int a = 12/0; //marry多100
userDao.addMoney();
//第三步 没有发生异常,提交数据
}catch (Exception e){
//第四步 如果出现异常,进行事务回滚
回滚操作....
}
}

(Spring事务操作)

操作步骤:1、在业务逻辑层(service)加入事务管理 2、在Spring里面进行事务管理操作(编程式事务管理|声明式事务管理)

声明式事务管理:1、注解方式 2、xml配置文件方式

声明式事务管理底层:AOP(面向切面方式)

事务管理API:

(1)提供了一个接口,代表事务管理器。这个接口针对不同的框架有不同的实现类(Interface:PlatformTransactionManager)

开始:

1.1、配置事务管理器开启事务注解

<!--dataSource-->
.....见前面配置
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务注解 tx和配置context一样-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
1.2、在service层的类或方法上添加事务的一个注解
@Service
@Transactional//表示类里面所有的方法都添加事务 可以单独的添加到类中需要添加事务的方法上
public class UserService {
//注入dao
@Autowired
private UserDao userDao; //转账操作
public void accountMoney() {
//lucy少100
userDao.reduceMoney(); //会出异常的代码
int a = 12/0; //marry多100
userDao.addMoney(); }
}

先将lucy和marry的钱全部修改为1000

执行测试类:

八月 03, 2020 10:24:25 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
//下面的是报错--可以认为转账过程中停电了,lucy和marry的钱不会多也不会少 各自还是1000元
java.lang.ArithmeticException: / by zero

事务操作(声明式事务管理配置)

@Transactional(参数说明)

@Transactional(propagation = Propagation.REQUIRED)  //事务
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ) **,//隔离级别
@Transactional( timeout = 5,{事务},{隔离级别}) //超时时间
@Transactional(readOnly = true,{超时时间},{事务},{隔离级别})//是否只读

事务方法:对数据库表数据进行变化的操作(增\删\查\改)

参数说明:
prepagation(7种行为)   --事务的传播行为,多事务方法之间进行调用,这个过程是如何接管的
行为1:REQUIED
如果有事务在运行,当前的方法就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行
[如果A方法本身有事务,调用B方法之后,B方法会使用当前A方法里面的事务]
[如果A方法本身没有事务,调用B方法之后,创建新事务]
-----
行为2:REQUIED_NEW
当前的方法必须重启新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
[使用A方法调用B方法,无论A方法是否有事务,都会创建新的事务]
-----
行为3:SUPPORTS
如果有事务在运行,当前的方法就在这个事务内运行,否则他可以不运行在事务中
-----
行为4:NO_RESOURCES
当前的方法不应该运行在事务中,如果有运行的事务,将它挂起
-----
行为5:MANDATORY
当前的方法必须在事务内部,如果没有正在运行的事务,抛出异常
-----
行为6:NEVER
当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常
-----
行为7:NESTED
如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新的事务,并在它自己的事务内运行 isolation(4个隔离行为) --事务的隔离级别
事务里面有一个特性成为隔离性(不考虑隔离性会出现下面的三个问题),多事务操作之间它们不会产生影响。不考虑隔离性会产生一系列问题
有三个读的问题:脏读、不可重复读、虚读
脏读:多个事务之间一个未提交的事务读取到了另一个未提交事务的数据(致命问题)
不可重复读:一个未提交的事务读取到了另一个提交事务的修改数据(普通现象)
虚读:一个未提交的事务读取到另一条事务添加的数据
所以隔离性可以解决这三个问题 (×=可解决,√=不可解决)
隔离行为1:DEAD UNCOMMITTED(未读已提交)
脏读:√ 不可重复读:√ 虚读:√
-----
隔离行为2:READ COMMITTED(读已提交)
脏读:× 不可重复读:√ 虚读:√
-----
隔离行为3:REPEATABLE READ(可重复读)
脏读:× 不可重复读:× 虚读:√
-----
隔离行为4:SERIALIZABLE(串行化)
脏读:× 不可重复读:× 虚读:×
----- timeout() --超时时间
事务需要在一定的时间内进行提交,如果不提交就会进行回滚操作
默认值-1(不超时) 按照秒 readOnly() --是否只读
读:查询操作。写:添加修改删除操作
默认值是false(表示可以查询,可以增删查改)
设置层true后,就只能进行查询操作。 rollbackFor() --回滚
设置运行中出现了哪些异常进行事务回滚 noRollbackFor() --不回滚
设置出现哪些异常它不进行事务回滚

Spring 事务管理 基于配置文件的更多相关文章

  1. Spring事务管理之几种方式实现事务

    1.事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...

  2. Spring事务管理之几种方式实现事务(转)

    一:事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...

  3. Spring事务管理(编码式、配置文件方式、注解方式)

    1.事务(https://www.cnblogs.com/zhai1997/p/11710082.html) (1)事务的特性:acdi (2)事务的并发问题:丢失修改,脏读,不可重复读 (3)事务的 ...

  4. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  5. 事务管理(下) 配置spring事务管理的几种方式(声明式事务)

    配置spring事务管理的几种方式(声明式事务) 概要: Spring对编程式事务的支持与EJB有很大的区别.不像EJB和Java事务API(Java Transaction API, JTA)耦合在 ...

  6. Spring事务管理(转)

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...

  7. [Spring框架]Spring 事务管理基础入门总结.

    前言:在之前的博客中已经说过了数据库的事务, 不过那里面更多的是说明事务的一些锁机制, 今天来说一下Spring管理事务的一些基础知识. 之前的文章: [数据库事务与锁]详解一: 彻底理解数据库事务一 ...

  8. Spring 事务管理高级应用难点剖析--转

    第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...

  9. 【转】Spring事务管理

    原文链接 在 Spring 中,事务是通过 TransactionDefinition 接口来定义的.该接口包含与事务属性有关的方法.具体如清单 1 所示: 清单 1. TransactionDefi ...

  10. Spring事务管理(详解+实例)

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...

随机推荐

  1. 《Vue.js 设计与实现》读书笔记 - 第11章、快速 Diff 算法

    第11章.快速 Diff 算法 11.1 相同的前置元素和后置元素 快速 Diff 算法包含预处理步骤,这借鉴了纯文本 Diff 算法的思路. 先把相同的前缀后缀进行处理,然后再比较中间部分. fun ...

  2. 彻底解决 user.config 文件损坏

    症状见 发生 Configuration system failed to initialize 错误的一个特例 解决的办法,在去读 user.settings 之前捕获错误,比如 Main() 里面 ...

  3. 基于 KubeSphere 的 Nebula Graph 多云架构管理实践

    本文是杭州站 Meetup 讲师乔雷根据其分享内容整理而成的文章. 图数据库是一种使用图结构进行语义查询的数据库,它使用节点.边和属性来表示和存储数据.图数据库的应用领域非常广泛,在反应事物之间联系的 ...

  4. 快速理解和使用stream流

    数据量越大,硬件内核数越多,stream流相比传统for循环速度越快. 原因是stream流是可以并行处理的. 如果要使用stream流,可以直接用flatmap把外层嵌套扁平化,只留下自己需要处理的 ...

  5. Nuxt.js 应用中的 build:done 事件钩子详解

    title: Nuxt.js 应用中的 build:done 事件钩子详解 date: 2024/10/21 updated: 2024/10/21 author: cmdragon excerpt: ...

  6. 全中国有多少公网IP地址?

    之前为了准备CTF比赛,搞了一个云服务器,顺便申请了一个公网IP. 看着申请到的IP地址,我突然想到了一个问题:不是早就说IP地址已经耗尽了吗,为什么我随便就能申请到,是谁在负责IP地址的管理分配,咱 ...

  7. WebUploader 文件上传,兼容ios和安卓

    var upImg = WebUploader.create({ auto: true, swf: 'webuploader-0.1.5/Uploader.swf', // 图片接收服务端. serv ...

  8. 开源一款AI聊天工具

    学习Spring AI项目,开发一款问答工具 AI大模型请注册并生成API密钥 获取API密钥地址:https://bigmodel.cn/console/overview 开源地址:LuckyAI ...

  9. spring基础配置原则

    spring框架本身有四大原则:1.使用pojo进行轻量级和最小侵入式开发2.通过依赖注入和基于接口编程实现松耦合3.通过AOP和默认习惯进行声明式编程4.使用AOP和模板减少模式化代码spring ...

  10. 题解:「NOIP2022 提高组」种花

    题解:「NOIP2022 提高组」种花 题目大意:给定一个 \(n \times m\) 的01矩阵,0表示可以种花,1表示土坑(无法种花),现在要在图上种出一个C型或F型(C,F横着的两条线的长度都 ...