iBatis第五章:事务管理
---------------------------- 1、什么是事务 ------------------------------
什么是事务?

需要注意的是,事务的概念不是针对某个特定的数据库的,而是针对所有数据库都需要遵循的一项原则。
我们先来看一个经典的示例,将设有两个银行账户,他们之间实现转账业务,在这个时候就需要有事务控制,否则将可能出现不可预期的错误。
初始余额信息如下:

1、假设A要给B转账 $1000 ,正常情况下应该是下面介过样子滴:

2、可是,情况可能会出现下面这样不尽人意滴:

出现这种情况的原因是,A用户去银行给B转账1000,A操作成功了,但是在B银行正在准备将A转过来的钱存入B的账户时,这个时候发生了异常,比如突然断电了,或者由于程序错误原因,导致钱没存入到B账户中,就发生了这样的一幕。
所以,可见我们通过事务来控制是多么的重重要,它能保证我们的数据处于一致的状态,达到如下的效果:

这主要是用到的事务的特性,将A转账和向B存款放在同一个事务中,如果其中某一步发生了错误,事务将进行回滚(即一旦B存款发生的错误,A的转账也失效,将A的钱回退回去),达到操作前得一个正确状态。
---------------------------- 2、事务的特性 ------------------------------
既然我们需要使用事务,那么我们首先的搞清楚事务具有哪些特性,只有熟悉了这些特性,我们才能更好的根据需要来使用事务管理我们的应用。

1、原子性:保证事务中的所有步骤属于同一个整体,要么全部成功,要么全部失败。
2、一致性:指数据需要处于一致的状态。
3、隔离性:由于数据库中的资源处于一个共享的状态,同一时刻可能有多个用户操作,可能造成数据紊乱的状态,所以需要通过隔离特性来控制,在某一时刻只能有一个用户操作,当这个用户操作完成后再让其他用户操作,以此保证数据的准确性。
4、持久性:数据库主要提供了数据持久化的功能,一旦某个操作成功提交之后,这些数据就处于一个持久化的状态了,处于一个安全的状态。
---------------------------- 3、自动事务、局部事务和全局事务 ------------------------------
3.1、自动事务:
对于我们执行一条SQL语句,这个时候一般不需要通过我们显示的管理事务,单其实事务依然是存在的,是数据库提供的一项隐式管理功能,它不需要我们显示的进行开始事务、提交事务等操作。这样事务称为自动事务管理。
需要注意的是:如果我们没显示的对事务进行管理,数据库就会为我们提供自动事务处理机制,无论我们的SQL语句是怎么样的。
3.2、局部事务

其实局部事务和全局事务主要从业务的范围上存在不同,例如我们进行本行转账,就可以通过局部事务控制,因为整个流程只涉及到一个应用程序和一个数据库,没有痛其他应用程序交互,在业务范围上相对较小。
3.3、全局事务
全局事务处理的是一个比较宽泛的业务逻辑,它可能跨越多个应用系统以及应用程序,使用逻辑与局部事务管理雷同,只是范围更加宽而已。

通过全局事务将A银行转账和B银行进账控制在同一个事务中,如果A和B都成功了才提交,只要有一方发生异常即回滚事务,整个流程失败,以此来控制数据的一致性。
---------------------------- 4、自定义事务 ------------------------------
自定义事务可以显示的控制事务,下面以一个银行转账的例子来说明:
1、定义一个账户实体
/**
* @author Administrator
* 账户实体类
*/
public class Account {
private int id;
private String account;
private int money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
2、编写SQL配置文件
<sqlMap>
<!-- 给类定义别名,简化代码 -->
<typeAlias alias="account" type="com.test.bean.Account"/>
<!-- 查询 -->
<select id="account_select" parameterClass="java.lang.String" resultClass="account">
select account,money from account where account=#account#
</select>
<!-- 更新 -->
<update id="account_update" parameterClass="account">
update account set money=#money# where account=#account#
</update>
</sqlMap>
3、测试事务控制
package com.test.dbutil;
import java.sql.SQLException;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.test.bean.Account;
public class TestAccount {
/**
* 测试事务控制转账
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TestAccount t = new TestAccount();
try {
t.exchange1("A", "C", 500);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 实现转账功能【已经事务控制】
* @param aname
* @param bname
* @param money
* @throws SQLException
*/
private void exchange(String aname,String bname, int money) throws SQLException{
SqlMapClient sqlMapClient = BaseDAO.getInstance();
try {
//1、开始事务
sqlMapClient.startTransaction();
/** 具体的事处理 **/
//a、到数据库查询出两个账户
Account a = (Account) sqlMapClient.queryForObject("account_select", aname);
Account b = (Account) sqlMapClient.queryForObject("account_select", bname);
if(a != null && b != null){
//b、设置账户的金额
a.setMoney(a.getMoney() - money); //a账户减少金额
b.setMoney(b.getMoney() + money); //b账户增加金额
//c、执行转账功能
int ak = sqlMapClient.update("account_update", a);
int bk = sqlMapClient.update("account_update", b);
if(ak != 1 || bk != 1){
throw new SQLException("转账失败");
}
}else{
throw new SQLException("输入的账户信息有误");
}
System.out.println("转账成功:账户"+aname+"已经成功向账户"+bname+"转账。\n转账金额:"+money);
//2、提交事务
sqlMapClient.commitTransaction();
}finally{
//3、结束事务
sqlMapClient.endTransaction();
}
}
/**
* 转行功能【未做事务控制】
* @param aname
* @param bname
* @param money
* @throws SQLException
*/
private void exchange1(String aname,String bname, int money) throws SQLException{
SqlMapClient sqlMapClient = BaseDAO.getInstance();
try {
//a、到数据库查询出两个账户
Account a = (Account) sqlMapClient.queryForObject("account_select", aname);
Account b = (Account) sqlMapClient.queryForObject("account_select", bname);
//a账户执行转账
a.setMoney(a.getMoney() - money);
sqlMapClient.update("account_update", a);
//b账户执行金额进账
b.setMoney(b.getMoney() + money);
sqlMapClient.update("account_update", b);
System.out.println("转账成功:账户"+aname+"已经成功向账户"+bname+"转账。\n转账金额:"+money);
}catch(Exception e){
throw new SQLException("转账失败");
}
}
}
通过测试我们可以发现,通过事务控制的,不会发生数据不一致的情况,二不通过事务控制的在发生异常的情况下不能保证数据的正确性。
iBatis第五章:事务管理的更多相关文章
- Testlink1.9.17使用方法(第五章 测试用例管理)
第五章 测试用例管理 QQ交流群:585499566 TestLink支持的测试用例的管理包含二层:分别为新建测试用例集(Test Suites).创建测试用例(Test Cases).可以把测试用例 ...
- Spring学习(五)事务管理
Spring 事务管理: 一.事务概念: 1.什么是事务? 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的 ...
- 第6章 事务管理 6.1 spring事务
事务管理——原子性.一致性.隔离性.持久性 理解spring对事务管理的支持 Spring提供对编码式和声明式事务管理的支持.编码式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP,面 ...
- JAVA / MySql 编程——第五章 事务、视图、索引、备份和恢复
1.事务(Transaction): 事务是将一系列数据操作绑成一个整体进行统一管理. 如果一事务执行成功,则咋子该事务中进行的所有数据更改均会提交,称为数据库中的永久成部分. 如果事务执行是遇到错误 ...
- springboot快速入门(五)——事务管理
一.入门 概念就不再赘述了,由于一般我们是通过service控制事务,这里给出注解式的示例: package com.example.demo; import com.example.demo.bea ...
- 流畅的python第十五章上下文管理器和else块学习记录
with 语句和上下文管理器for.while 和 try 语句的 else 子句 with 语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文.这么做能避免错误并减少样板代码, ...
- Spring中的事务管理详解
在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...
- CSS3秘笈:第五章
第五章 层叠管理样式 1.层叠是决定哪些样式属性要被应用到某一个元素的一套规则. 2.最近的祖先样式胜出:浏览器会采用离相关标签最近的样式. 3.直接应用的样式胜出:任何直接应用于指定标签的样式都战 ...
- 跟我学Spring3(9.2):Spring的事务之事务管理器
原文出处: 张开涛9.2.1 概述 Spring框架支持事务管理的核心是事务管理器抽象,对于不同的数据访问框架(如Hibernate)通过实现策略接口PlatformTransactionManage ...
随机推荐
- SSM框架视频资料
SSM框架视频资料 进行过 Java Web 项目开发的同学,可能都知道 SSM 框架,即 Spring + SpringMVC + Mybatis .很多项目的主体框架都是采用这种模式,这也是 Ja ...
- WordPress怎样设置菜单栏旋转小图标
最近我在浏览别的博客的文章时,无意间发现了一个很好看的小装饰.那就是在WordPress菜单栏上的小图标.于是我研究了研究,弄到了设置方法之后决定把它分享出来. 菜单栏的小图标 设置步骤: 1, 我们 ...
- SQL Server统计信息偏差影响表联结方式案例浅析
我们知道数据库中的统计信息的准确性是非常重要的.它会影响执行计划.一直想写一篇关于统计信息影响执行计划的相关博客,但是都卡在如何构造一个合适的例子上,所以一直拖着没有写.巧合,最近在生产环境中遇到 ...
- UEditor单图上传跨域问题解决方案
UEditor UEditor是百度团队提供的富文本编辑器 git地址为:https://github.com/fex-team/ueditor 在最近的项目中使用了该插件作为项目的富文本编辑器 由于 ...
- PHP全栈学习笔记2
php概述 什么是php,PHP语言的优势,PHP5的新特性,PHP的发展趋势,PHP的应用领域. PHP是超文本预处理器,是一种服务器端,跨平台,HTML嵌入式的脚本语言,具有c语言,Java语言, ...
- vs 2017 vs code
vs 2017 Enterprise: NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Professional: KBJFW-NXHK6-W4WJM-CRMQB-G3CDH ==== ...
- 内核ring buffer -- kfifo
目前kernel的kfifo根据版本有两种形式, 早期的函数形式和现在的宏定义形式 1. 早期的(linux-3.0.56/kernel/kfifo.c) 感兴趣读者可以自己看, 源码如下: /* * ...
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二九║ Nuxt实战:异步实现数据双端渲染
回顾 哈喽大家好!又是元气满满的周~~~二哈哈,不知道大家中秋节过的如何,马上又是国庆节了,博主我将通过三天的时间,给大家把项目二的数据添上(这里强调下,填充数据不是最重要的,最重要的是要配合着让大家 ...
- 【深度学习】--GAN从入门到初始
一.前述 GAN,生成对抗网络,在2016年基本火爆深度学习,所有有必要学习一下.生成对抗网络直观的应用可以帮我们生成数据,图片. 二.具体 1.生活案例 比如假设真钱 r 坏人定义为G 我们通过 ...
- 【深度学习篇】--Seq2Seq模型从初识到应用
一.前述 架构: 问题: 1.压缩会损失信息 2.长度会影响准确率 解决办法: Attention机制:聚焦模式 “高分辨率”聚焦在图片的某个特定区域并以“低分辨率”,感知图像的周边区域的模式.通过大 ...