Spring 事务管理 基于配置文件
事务概念:
原子性:要么都成功,有一个失败都失败
一致性:总量不变(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 事务管理 基于配置文件的更多相关文章
- Spring事务管理之几种方式实现事务
1.事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...
- Spring事务管理之几种方式实现事务(转)
一:事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...
- Spring事务管理(编码式、配置文件方式、注解方式)
1.事务(https://www.cnblogs.com/zhai1997/p/11710082.html) (1)事务的特性:acdi (2)事务的并发问题:丢失修改,脏读,不可重复读 (3)事务的 ...
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
- 事务管理(下) 配置spring事务管理的几种方式(声明式事务)
配置spring事务管理的几种方式(声明式事务) 概要: Spring对编程式事务的支持与EJB有很大的区别.不像EJB和Java事务API(Java Transaction API, JTA)耦合在 ...
- Spring事务管理(转)
1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...
- [Spring框架]Spring 事务管理基础入门总结.
前言:在之前的博客中已经说过了数据库的事务, 不过那里面更多的是说明事务的一些锁机制, 今天来说一下Spring管理事务的一些基础知识. 之前的文章: [数据库事务与锁]详解一: 彻底理解数据库事务一 ...
- Spring 事务管理高级应用难点剖析--转
第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...
- 【转】Spring事务管理
原文链接 在 Spring 中,事务是通过 TransactionDefinition 接口来定义的.该接口包含与事务属性有关的方法.具体如清单 1 所示: 清单 1. TransactionDefi ...
- Spring事务管理(详解+实例)
1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...
随机推荐
- Go语言中的位运算符
位运算(bitwise operations)是计算机科学中非常基础且重要的运算类型,它直接操作二进制位.Go语言中提供了一组位运算符,用于执行位级别的操作. Go语言中的位运算符 按位与(& ...
- pcss 软阴影
PCF Percentage Closer Filtering:PCF是一种用于阴影反锯齿的方法,本身不是软阴影方法. 算法流程说明: Perform multiple (e.g. 7x7) dept ...
- 2021年第十一届数据技术嘉年华(DTC)资料分享
数据技术嘉年华(DTC)是由由中国DBA联盟(ACDU)和墨天轮社区联合主办的数据技术领域的盛会,至今已成功举办11届,吸引和聚集了众多数据领域学术精英.领袖人物.技术专家.从业者和技术爱好者,于此进 ...
- 简化版本的redis配置文件
# bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 #bind 127.0.0.1 protected-mode no port 6379 tcp-b ...
- 1. java + react 实现 HRM
1. 云服务的三种方式 1.1 IAAS 基础设施即服务 ,只会提供基础的设施,eg:服务器,网络等 : 1.2 PAAS 平台即服务 ,提供平台,可以把自己写好的代码部署到平台上 : 1.3 SAA ...
- day17-打印三角形及Debug
打印三角形 之前学习C++的时候也曾做过,于是乎凭借记忆又试了试,也还能试出来.代码如下: #include<stdio.h> int main(){ int i,j; for(i= ...
- Nacos2.3.2在ubuntu中的部署
Nacos2.3.2 在ubuntu下的部署 下载地址 发布历史 | Nacos 官网 https://download.nacos.io/nacos-server/nacos-server-2.3. ...
- 这些HTTP协议状态码你知道吗?
使用ASP.NET/PHP/JSP 或者javascript都会用到http的不同状态,一些常见的状态码为: 200 – 服务器成功返回网页 404 – 请求的网页不存在 503 – 服务不可用 1x ...
- CMDB实践指南:项目规划与实施策略解析
随着现代企业IT系统的日益复杂,如何有效管理这些庞大的IT资产和资源,成为每个企业必须面对的重要问题.CMDB应运而生,帮助企业集中管理IT资源,维护系统的稳定性,并支持故障排查与决策制定.本文将深入 ...
- Cartographer的扫描匹配
cartographer 代码思想解读(1)- 相关匹配 cartographer在2016年开源后一直在使用,但是一直未仔细阅读并分析其核心代码结构.目前网上可以找到许多博主对其分析和理解.其car ...