买书的例子 程序应该将图书数量的操作和更新account用户余额的操作作为一个事务来处理,只有这两个操作都完成的情况下,才能提交事务,否则就回滚事务。

本文转自http://blog.chinaunix.net/uid-26284395-id-3037410.html,感谢作者

  1. conn=DriverManager.getConnection(url,user,password);
  2. conn.setAutoCommit(false);
  3. conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
  4. stmt=conn.createStatement();
  5. rs=stmt.executeQuery("select price,amount from bookinfo where id=3");
  6. rs.next();
    1. conn.commit();
    2. out.println("交易成功!");
    3. out.close();
    4. }
    5. catch(SQLException se)
    6. {
    7. if(conn!=null)
    8. {
    9. try
    10. {
    11. conn.rollback();
    12. }
    13. catch(SQLException ***)
    14. {
    15. ***.printStackTrace();
    16. }
    17. }
    18. se.printStackTrace();
    19. }
    20. finally
    21. {
    22. if(rs!=null)
    23. {
    24. try
    25. {
    26. rs.close();
    27. }
    28. catch(SQLException se)
    29. {
    30. se.printStackTrace();
    31. }
    32. rs=null;
    33. }
      1. (2)设置事务回滚点

        Savepoint sp = conn.setSavepoint();

        Conn.rollback(sp);

        Conn.commit();   //回滚后必须要提交

        package com.itheima.transaction;

        import Java.sql.Connection;

        import java.sql.DriverManager;

        import java.sql.PreparedStatement;

        import java.sql.SQLException;

        import java.sql.Savepoint;

        import org.junit.Test;

        import com.itheima.util.DaoUtil;

        public class Demo1 {

        @Test

        public void test1(){

        Connection conn = null;

        PreparedStatement ps1 = null;

        PreparedStatement ps2 = null;

        Savepoint sp = null;

        try{

        Class.forName("com.MySQL.jdbc.Driver");

        conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");

        conn.setAutoCommit(false);

        ps1 = conn.prepareStatement("update account set money = money+100 where name=?");

        ps1.setString(1, "b");

        ps1.executeUpdate();

        //int i = 1/0;

        ps2 = conn.prepareStatement("update account set money = money-100 where name=?");

        ps2.setString(1, "a");

        ps2.executeUpdate();

        sp = conn.setSavepoint();

        //-----------------------------------

        ps1 = conn.prepareStatement("update account set money = money+100 where name=?");

        ps1.setString(1, "b");

        ps1.executeUpdate();

        int i = 1/0;

        ps2 = conn.prepareStatement("update account set money = money-100 where name=?");

        ps2.setString(1, "a");

        ps2.executeUpdate();

        conn.commit();

        }catch (Exception e) {

        e.printStackTrace();

        try {

        if(sp !=null){

        conn.rollback(sp);

        conn.commit();

        }else{

        conn.rollback();

        }

        } catch (SQLException e1) {

        // TODO Auto-generated catch block

        e1.printStackTrace();

        }

        }finally{

        DaoUtil.close(conn, ps1, null);

        DaoUtil.close(conn, ps2, null);

        }

        }

        }

        JDBC API支持事务对数据库的加锁,并且提供了5种操作支持,2种加锁密度。

        5种加锁支持为:

        static int TRANSACTION_NONE = 0;

        static int TRANSACTION_READ_UNCOMMITTED = 1;

        static int TRANSACTION_READ_COMMITTED = 2;

        static int TRANSACTION_REPEATABLE_READ = 4;

        static int TRANSACTION_SERIALIZABLE = 8;

        1. 5、事务的隔离级别

          (1)多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。

          (2)如果不考虑隔离性,可能会引发如下问题:

          脏读(dirty reads)

          一个事务读取了另一个未提交的并行事务写的数据。

          不可重复读(non-repeatable reads)

          一个事务重新读取前面读取过的数据, 发现该数据已经被另一个已提交的事务修改过。

          幻读(phantom read)

          一个事务重新执行一个查询,返回一套符合查询条件的行, 发现这些行因为其他最近提交的事务而发生了改变。

          6、事务的隔离性

          (1)脏读:

          指一个事务读取了另外一个事务未提交的数据。

          这是非常危险的,假设A向B转帐100元,对应sql语句如下所示

          1.update account set money=money+100 while name=‘b’;

          2.update account set money=money-100 while name=‘a’;

          当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。

          a 1000

          b 1000

          a:

          start transaction;

          update account set money=money-100 where name='a';

          update account set money=money+100 where name='b';

          b:

          start transaction;

          select * from account where name='b';

          a:

          rollback;

          b:

          strat transaction;

          select * from account where name='b';

          (2)不可重复读:

          在一个事务内读取表中的某一行数据,多次读取结果不同。

          例如银行想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户存了100元并提交了,银行接着又进行了一次查询,此时A帐户为300元了。银行两次查询不一致,可能就会很困惑,不知道哪次查询是准的。

          和脏读的区别是,脏读是读取前一事务未提交的脏数据,不可重复读是重新读取了前一事务已提交的数据。

          很多人认为这种情况就对了,无须困惑,当然是后面的为准。我们可以考虑这样一种情况,比如银行程序需要将查询结果分别输出到电脑屏幕和写到文件中,结果在一个事务中针对输出的目的地,进行的两次查询不一致,导致文件和屏幕中的结果不一致,银行工作人员就不知道以哪个为准了。

          a 1000

          b 1000

          start transaction;

          select sum(money) from account; ---- 总存款:2000

          select count(*) from account; ---- 总账户数:2

          -------------------------

          b:

          start transaction;

          update account set money = money-1000 where name='b';

          commit;

          -------------------------

          select avg(money) from account; ---- 账户平均金额:500

          (3)虚读(幻读)

          是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

          如丙存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后丙提交了,这时银行再统计发现帐户为600元了,造成虚读同样会使银行不知所措,到底以哪个为准。

          a 1000

          b 1000

          c 1000

          start transaction;

          select sum(money) from account; ---- 总存款:2000

          -------------------------

          c:

          start transaction;

          insert into account values(null,'c',1000);

          commit;

          -------------------------

          select count(*) from account; ---- 总账户数:3

          7、事务隔离性的设置语句

          数据库共定义了四种隔离级别:

          Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)

          Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)不可以避免虚读

          Read committed:可避免脏读情况发生(读已提交)

          Read uncommitted:最低级别,以上情况均无法保证。(读未提交)

          set [global/session]  transaction isolation level 设置事务隔离级别

          select @@tx_isolation查询当前事务隔离级别

          安全性来说:Serializable>Repeatable read>Read committed>Read uncommitted

          效率来说:Serializable<Repeatable read<Read committed<Read uncommitted

          通常来说,一般的应用都会选择Repeatable read或Read committed作为数据库隔离级别来使用。

          mysql默认的数据库隔离级别为:REPEATABLE-READ

          如何查询当前数据库的隔离级别?select @@tx_isolation;

          如何设置当前数据库的隔离级别?set [global/session] transaction isolation level ...;

          ~此种方式设置的隔离级别只对当前连接起作用。

          set transaction isolation level read uncommitted;

          set session transaction isolation level read uncommitted;

          ~此种方式设置的隔离级别是设置数据库默认的隔离级别

          set global transaction isolation level read uncommitted;

          8、事务的丢失更新问题(lost update )

          (1)两个或多个事务更新同一行,但这些事务彼此之间都不知道其它事务进行的修改,因此第二个更改覆盖了第一个修改

          (2)共享锁:共享锁和共享锁可以共存。共享锁和排他锁不能共存。在Serializable隔离级别下一个事务进行查询操作将会加上共享锁。

          (3)排他锁:排他锁和所有锁都不能共存。无论什么隔离级别执行增删改操作时,会加上排他锁

          (4).数据库设计为Serializable隔离级别,就可以防止更新丢失问题。

          乐观锁和悲观锁并不是数据库中真实存在的锁,是我们如何利用共享和排他锁解决更新丢失问题的两种解决方案,体现了人们看待事务的态度:

          悲观锁:悲观的认为大部分情况下进行操作都会出现更新丢失问题。

          在每次进行查询的时候,都手动的加上一个排他锁。

          select * from table lock in share mode(读锁、共享锁)

          select * from table for update (写锁、排它锁)

          乐观锁:乐观的认为大部分的情况下都不会有更新丢失问题。通过时间戳字段,

          在表中设计一个版本字段version,当每次对数据库中的数据进行修改操作时,版本号都要进行增加。

          (5)如果我的程序修改比较少查询比较多:乐观锁

          如果我的程序查询比较少修改比较多:悲观锁

jdbc事务的更多相关文章

  1. JTA和JDBC事务

    一般情况下,J2EE应用服务器支持JDBC事务.JTA事务.容器管理事务.这里讨论JTA和JDBC事务的区别.这2个是常用的DAO模式事务界定方式.JDBC 事务 JDBC 事务是用 Connecti ...

  2. JDBC 事务控制

    一.简介: 前面一遍提到了jdbc事务相关的概念.从中了解到事务应具有ACID特性.所以对于javaweb开发来说,某一个service层的方法,应该是一个事务,应该是具有原子性的.特别是当一个ser ...

  3. Java的JDBC事务详解(转)

    事务的特性: 1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行. 2) 一致性(consistency):事务在完 ...

  4. Java中的事务——JDBC事务和JTA事务

    Java中的事务——JDBC事务和JTA事务 转载:http://www.hollischuang.com/archives/1658 之前的事务介绍基本都是数据库层面的事务,本文来介绍一下J2EE中 ...

  5. CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

    JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...

  6. JDBC事务和JTA事务的区别

    转自:JDBC和JTA事务的区别 一.事务概述事务表示一个由一系列的数据库操作组成的不可分割的逻辑单位,其中的操作要么全做要么全都不做.与事务相关的操作主要有:BEGIN TRANSACTION: 开 ...

  7. JDBC 事务隔离级别

    JDBC 事务隔离级别     先解释一下:a:脏读取:一个事务读取了另外一个并行事务未提交的数据b:不可重复读取:一个事务再次读取之前的数据时得到的数据不一致,被另外一个事务修改c:虚读:一个事务重 ...

  8. Java的JDBC事务详解

    Java的JDBC事务详解         分类:             Hibernate              2010-06-02 10:04     12298人阅读     评论(9) ...

  9. 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

    1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...

  10. 春天JDBC事务管理

    JDBC事务管理 春天提供编程式的事务管理(编程式事务管理)与声明式的事务管理(声明式事务management),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管 ...

随机推荐

  1. silverlight Frame嵌套页面刷新问题

    1.此方法将会刷新到主页面 private void btn_Click(object sender, RoutedEventArgs e) { HtmlPage.Window.Eval(" ...

  2. javascript 创建对象及对象原型链属性介绍

    我们知道javascript里定义一个普通对象的方法,如: let obj = {}; obj.num = 1; obj.string = 'string'; obj.func = function( ...

  3. jquery如何通过name名称获取当前name的value值

    本文为大家介绍下jquery通过name名称获取当前name的value值的具体实现,感兴趣的朋友可以参考下. 复制代码代码如下: $("*[name='name']").val( ...

  4. PHP版本中的VC6,VC9,VC11,TS,NTS区别

    以windows为例,看看下载到得php zip的文件名 php-5.4.4-nts-Win32-VC9-x86.zip VC6:legacy Visual Studio 6 compiler,是使用 ...

  5. Eclipse 代码提示功能设置。

    1.        解决实例化时自动补全不必要的单词问题 2.        以MyEclipse 6.5重新配图 鉴 于网上的批评之声甚大,我只想说明我的想法:这样的增强代码提示,最终是用来辅助我们 ...

  6. About Curah

    相信下列场景对您来说一点都不陌生:您遇到一个问题,花了好几个小时在网上搜寻解答和可靠的技术内容.即使前往许多技术博客和论坛翻箱倒柜后,还是无法确定要相信谁,也不知道该选哪个答案. Curah! 网站就 ...

  7. python之super()函数

    python之super()函数 python的构造器奇特, 使用魔方. 构造器内对基类对象的初始化同样也很奇特, 奇特到没有半点优雅! 在构造器中使用super(class, instance)返回 ...

  8. IEEE802是一个局域网标准系列

    视频教程 http://v.youku.com/v_show/id_XNjgyODA0NzE2.html?from=s1.8-1-1.2 干线 总线+环形网的传递机制 环形令牌总线 802.4 

  9. Bluetooth

    Android provides a default Bluetooth stack, BlueDroid, that is divided into two layers: The Bluetoot ...

  10. HDU 4681 String 最长公共子序列

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4681 题意: 给你a,b,c三个串,构造一个d串使得d是a,b的子序列,并且c是d的连续子串.求d最大 ...