java事务处理

有个同学给我的文档,直接发上来了,


在数据库操作中,一项事务是指由一条或多条对数据库更新的sql语句所组成的一个不可分割的工作单元。只有当事务中的所有操作都正常完成了,整个事务才能被提交到数据库,如果有一项操作没有完成,就必须撤消整个事务。 



例如在银行的转帐事务中,假定张三从自己的帐号上把1000元转到李四的帐号上,相关的sql语句如下: 

update account set monery=monery-1000 where name='zhangsan' 
update account set monery=monery+1000 where name='lisi' 


这个两条语句必须作为一个完成的事务来处理。只有当两条都成功执行了,才能提交这个事务。如果有一句失败,整个事务必须撤消。 

在connection类中提供了3个控制事务的方法: 


(1) setAutoCommit(Boolean autoCommit):设置是否自动提交事务; 
(2) commit();提交事务; 
(3) rollback();撤消事务; 

在jdbc api中,默认的情况为自动提交事务,也就是说,每一条对数据库的更新的sql语句代表一项事务,操作成功后,系统自动调用commit()来提交,否则将调用rollback()来撤消事务。 

在jdbc api中,可以通过调用setAutoCommit(false) 来禁止自动提交事务。然后就可以把多条更新数据库的sql语句做为一个事务,在所有操作完成之后,调用commit()来进行整体提交。倘若其中一项 sql操作失败,就不会执行commit()方法,而是产生相应的sqlexception,此时就可以捕获异常代码块中调用rollback()方法撤消事务。
示例:
有这样一张名叫test_user的表:uid为1的money为0元,uid为2的money为300元,uid为3的money为800元。现在uid为3的人向uid为1的人转账,每次50元。当uid为3的人的账户中的money少于或等于700的元的时候,则停止转账。也就是说,最后的uid为1的人账户为100元,uid为3的账户700元。
事务操作的基本流程是:当达到某个条件时抛出一个异常,在这个异常处理中回滚操作。事务最大的一个特点是,要么全部执行,要么不执行。但是,对于使用JAVA来操作数据库事务来说,并没用我们想的那么简单:下面这段代码故意将某个字段写错,来检验java是如何操作数据库的事务的:


public class TransactionTest { 
public static void main(String[] args) throws Exception  { Connection conn = ConnectionFactory.getInstance().getLocalConnection(); //换成自己的连接代码int money=0; ResultSet rt=null; try { conn.setAutoCommit(false); //修改提交方式,关闭自动提交模式Statement st =conn.createStatement();    String addMoneySql = "update test_user set money=money+50 where uid=1;"; int flag0=  st.executeUpdate(addMoneySql); System.out.println(flag0); String reduceMoneySql = "update test_user set money=money-50 where uid=3"; int flag1   =st.executeUpdate(reduceMoneySql); System.out.println(flag1); String queryMoneySql="select money from test_user where uid=3"; rt=st.executeQuery(queryMoneySql); if(rt.next()){ money=rt.getInt("mone");//这里故意将字段打错,检验java如何执行事务的,原字段为money System.out.println(money); } if(money<=700){ throw new RuntimeException("3号的钱已经不够了,不要汇款了");//抛出一个异常,在异常处理中回滚操作 } conn.commit(); } catch (Exception e) { e.printStackTrace();//打印出上面抛出来的异常,否则是不会显示的。 if(conn!=null){ conn.rollback(); } } } 
}


执行这段代码。发现结果为:
 
1
1
java.sql.SQLException: Column 'mone' not found.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
at com.mysql.jdbc.ResultSet.findColumn(ResultSet.java:987)
at com.mysql.jdbc.ResultSet.getInt(ResultSet.java:2749)
at TransactionTest.main(TransactionTest.java:26)


在异常发生后,catch住异常,执行了回滚操作,查看数据库,数据库数据并没有发生变化。但是用update执行的结果来看,update是执行了的。这就说明java处理数据库的事务的执行策略:先挨句执行(下一句的基本数据是上一句执行完毕的数据,而不是数据库真实的数据),当出现回滚时候,直接通知数据库回滚。数据库回滚以后并不会通知java,所以就会出现打印执行结果与数据库数据不一致的情况。


那么,这一段代码中money(假设字段已经修改正常)的值会是多少呢?
首先 uid 1 加50,uid 3 减50,成功执行,打印出750
然后 uid 1加 50 uid 3减 50,此时 uid 3中的money为 700(发现异常,回滚)结果数据库中的uid还是750,而打印出来的值却是 700.
再执行。发现依旧会抛出3号钱已经不够的异常。
当然,我们会思考,我们重新执行这段代码的话,java是不会从数据库中间取得数据,而是直接使用脏数据。而且关闭连接等资源,关闭eclispe都不起作用,只有重新启动数据库,才能使得java从数据库读数据。
当然了,将事务按照合理的方式编排就不会出现这种错误。比如,将select语句放在uid 3之前,就不会出错了。 。(其实对于事务操作,依旧读的是脏数据,只不过这个脏数据与实际数据一致罢了。)

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

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

相关文章

vsftp配置参数

vsftp配置参数 转载&#xff1a;http://blog.chinaunix.net/uid-134240-id-172158.html listen_addressip address 指定侦听IP listen_portport_value 指定侦听端口&#xff0c;默认21 anonymous_enableYES 是否允许使用匿名帐户 local_enableYES 是否允许本地用户登录 …

Java文件类boolean canWrite()方法(带示例)

文件类boolean canWrite() (File Class boolean canWrite()) This method is available in package java.io.File.canRead(). 软件包java.io.File.canRead()中提供了此方法。 This method is used to write the file and the file is represented by the abstract filepath or …

案例:Redis 问题汇总和相关解决方案

本文收集了一些 Redis 使用中经常遇到的一些问题,和与之相对应的解决方案,这些内容不但会出现在实际工作中,也是面试的高频问题,接下来一起来看。 缓存雪崩 缓存雪崩是指在短时间内,有大量缓存同时过期,导致大量的请求直接查询数据库,从而对数据库造成了巨大的压力,严…

实战:Redis 集群模式(下)

上篇文章我们讲了 Redis 集群的搭建与节点的动态添加和删除,我们这里再来简单的复习一下,其中 30001~30006 是我们最初搭建的集群,而 30007 和 30008 是后面动态添加的主从节点,我们使用 --cluster info 命令来看一下主节点和槽位的分配情况,执行代码如下: $ redis-cli …

计网百度脑图

第一章概述 第二章物理层 第三章数据链路层 第四章网络层 第五章运输层

Java Integer类highestOneBit()方法与示例

整数类highestOneBit()方法 (Integer class highestOneBit() method) highestOneBit() method is available in java.lang package. maximumOneBit()方法在java.lang包中可用。 highestOneBit() method is used to find almost only single 1s bit from the leftmost side one …

转载:JAVA获取时间戳,哪个更快

转载&#xff1a;http://hi.baidu.com/suofang/item/96629a060a44c119eafe38cc 目前获取毫秒值大概有下面三种方法 Java代码 //方法 一 System.currentTimeMillis(); //方法 二 Calendar.getInstance().getTimeInMillis(); //方法 三 new Date().getTime(); //方法…

加餐:Redis 的可视化管理工具

因为 Redis 官方只提供了命令行版的 Redis 客户端 redis-cli,以至于我们在使用的时候会比较麻烦,通常要输入一堆命令,而且命令行版的客户端看起来也不够直观,基于以上两个原因我们需要找一个可视化的 Redis 客户端,下面是我这些年使用过的一些 Redis 可视化客户端,分享给…

第一次创建springboot框架项目

第一次创建springboot框架项目1.1_创建步骤2.1_启动时遇到的问题2.2_启动响应网页测试2.3_连接数据库尝试1.1_创建步骤 &#xff08;1&#xff09;创建spring项目 &#xff08;2&#xff09; &#xff08;3&#xff09; 加入引擎 下一步即可 2.1_启动时遇到的问题 &a…

JAVA学习--集合的遍历

1 Test2 public void testFor3(){3 String[] str new String[]{"AA","BB","DD"};4 for(String s : str){5 s "MM";//此处的s是新定义的局部变量&#xff0c;其值的修改不会对str本身造成影响。6 …

技能学习指南

经过前面文章的学习,我相信一定有一半的人看懂了,而另一半人一定是似懂非懂或者是完全不懂,如果你属于前者,那恭喜你,但如果没看懂,也没关系,本文来给你具体的解决方案。 我们来仔细回忆两件事,第一件是大学考级学的那些英语,我每个单词每个语句当时都背的滚瓜烂熟,…

转载:VB监视进程

从百度知道看的&#xff0c;VB监视进程&#xff1a; 让VB程序监视进程中的名称“Windows 任务管理器”,和“AAA”两个进程的进程名&#xff0c;而且进行操作&#xff1a;如果“Windows 任务管理器”被关闭时则自动关闭“进程某某”程序&#xff01;可以用一个 Timer 定时执行下…

Java字符类isLowerCase()方法与示例

字符类isLowerCase()方法 (Character class isLowerCase() method) isLowerCase() method is available in java.lang package. isLowerCase()方法在java.lang包中可用。 isLowerCase() method is used to check whether the given char value is lowercase or not. isLowerCas…

JPA使用

JPA使用1.1_persistence使用问题1.1_persistence使用问题 import javax.persistence.*; 需要在pom文件加入依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>&…

附录:更多字典操作命令

插入一个或多个元素 语法:hmset key field value [field value …] 示例: 127.0.0.1:6379> hmset myhash k1 val1 k2 val2 OK 127.0.0.1:6379> hmget myhash k1 k2 1) "val1" 2) "val2"查询一个或多个元素 语法:hmget key field [field …] 示…

Movie

悬疑片&#xff1a; 嫌疑人X的献身转载于:https://www.cnblogs.com/lnlvinso/p/4264804.html

hibernate中对象的3种状态----瞬时态、持久态、脱管态

转载&#xff1a; http://www.blogjava.net/amigoxie/archive/2007/02/11/99342.htmlHibernate的对象有3种状态&#xff0c;分别为&#xff1a;瞬时态(Transient)、 持久态(Persistent)、脱管态(Detached)。处于持久态的对象也称为PO(Persistence Object)&#xff0c;瞬时对象和…

java 根据类名示例化类_Java LocalDateTime类| ofInstant()方法与示例

java 根据类名示例化类LocalDateTime类的Instant()方法 (LocalDateTime Class ofInstant() method) ofInstant() method is available in java.time package. ofInstant()方法在java.time包中可用。 ofInstant() method is used to create an instance of LocalDateTime from t…

附录:更多字符串操作命令

键值对过期操作 a.添加键值对并设置过期时间 语法:set key value [expiration EX seconds|PX milliseconds] [NX|XX] 示例: 127.0.0.1:6379> set k1 val1 ex 1000 OK设置键值对 k1=val1,过期时间为 1000 秒。 查询键的过期时间可以使用 ttl key,如下代码所示: 127.…

ACM - 第6章 数据结构基础(2)

6.4.2 走迷宫 利用bfs寻找最短路。通过对u/m得到x&#xff0c;u%m得到y。u x * m y 将方向保存在dx[], dy[]中。 cint q[maxn*maxn]; void bfs(int x, int y) {int front 0, rear 0, d, u;u x*m y;vis[x][y] 1; fa[x][y] u; dist[x][y] 0;q[rear] u;while(front <…