• MySql事务及JDBC对事务的使用


     一 、事务的几个重要特性

    1. 原子性

      事务内的每个内容不可分割,是一个统一的整体。或同时进行或同时消亡。

    2.一致性

          事务执行前和事务执行后,状态都是统一的。如A转B 100元,A和B数据总额度没有在这个转账过程中增加或者减小。

    3.隔离性【isolation】

      事务的隔离性指的是几个事务同时执行,事务a不应该干扰到事务b内的操作(在并发过程中很有可能会发生事务间的影响,例如脏读、不可重复读等。需要在编程的时候选择适当的方式进行选择)

    3.可持久性

      事务执行后的结果可以存储(序列化)到硬盘上,形成一个固定的内容存储起来。

     

     二、事务的使用

      事务的生命周期有2个,1开启事务 2提交或者回滚事务。事务开始后一定要提交或者回滚,以免引起数据库内存泄漏

      使用Mysql开启事务及使用。

      表内数据如下,现需要从a账号转100money到b账号。

     

    具体步骤如下:

       Mysql 中与事务使用有关的三个关键语句:

          (1) 开启事务 : start transaction

          (2)回滚事务 :rollback , 提交事务:commit

     三、使用JDBC对事务进行调用

     △注意: 事务只能对DML语句进行操作,对数据定义类语句DDL无法操作,例如建表、建立索引、建立分区等。

     JDBC使用事务时,需要使用Java语言中的Connection对事务进行操作,具体的事务对应一个数据库连接。

     1 package com.scl.test.transcaction;
     2 
     3 import java.sql.Connection;
     4 import java.sql.Statement;
     5 
     6 import org.junit.Test;
     7 
     8 public class TestTranscaction
     9 {
    10 
    11     @Test
    12     public void testTransaction() throws Exception
    13     {
    14         Connection conn = null;
    15         Statement statement = null;
    16 
    17         try
    18         {
    19             conn = JDBCHelper.getConnection();
    20 
    21             conn.setAutoCommit(false); //开启事务,禁止自动提交
    22             String sql1 = "update t_account t set t.money=t.money-100 where t.name ='a'";
    23             String sql2 = "update t_account t set t.money=t.money+100 where t.name ='b'";
    24             statement = conn.createStatement();
    25             // statement.setString(1, "a");
    26 
    27             statement.addBatch(sql1);
    28             statement.addBatch(sql2);
    29 
    30 
    31             statement.executeBatch();
    32             conn.commit(); //执行成功,提交事务
    33 
    34         }
    35         catch (Exception e)
    36         {
    37             conn.rollback(); //发生异常,事务回滚
    38         }
    39         finally
    40         {
    41             JDBCHelper.disposeConnect(statement, conn);
    42         }
    43     }
    44 }
    View Code

      最后进行一个知识点补漏:JDBC执行多条sql脚本。

      JDBC提供了执行多条sql语句的方法,使用PrepareStatement或Statement实例调用addBatch方法。目前发现该方法有几个缺点:

      1. 无法通过PrepareStatement实例对多条不同的sql脚本进行参数化设置。因为PrepareStatement是由一个链接产生的,不能同时用一个prepareStatement实例同时对应两个不同的预处理文件。

       如需求:需要插入更新一张表里面的两行不同的数据。 

            sql1: update t_account t set t.money=t.money-100 where t.name ='a';

       sql2: update t_account t set t.money=t.money-100 where t.name ='b';

       这时候没办法使用prepareStatement的addBatch方法执行操作。见代码:

     1     @Test
     2     public void testTransaction() throws Exception
     3     {
     4         Connection conn = null;
     5         Statement st = null;
     6         PreparedStatement pst = null;
     7         try
     8         {
     9             conn = JDBCHelper.getConnection();
    10 
    11             conn.setAutoCommit(false);
    12             String sql1 = "update t_account t set t.money=t.money-100 where t.name =?";
    13             String sql2 = "update t_account t set t.money=t.money+100 where t.name =?";
    14             pst = conn.prepareStatement(sql1);
    15             // 只能批量执行某一条固定的sql语句,并且进行参数化设置
    16             pst.setString(1, "a"); // 为name 为 a的用户减少100元
    17             pst.addBatch();
    18             pst.setString(1, "b"); // 为name 为b的用户减少100元
    19             pst.addBatch();
    20             pst.executeBatch(); // 只能在执行完成以后提交一次,然后改成新的sql脚本。但容易引发内存泄漏
    21 
    22             pst = conn.prepareStatement(sql2); // 内存泄漏,存在未关闭的链接
    23             pst.setString(1, "c");
    24             pst.addBatch();
    25             pst.executeBatch();
    26             conn.commit();
    27 
    28         }
    29         catch (Exception e)
    30         {
    31             conn.rollback();
    32         }
    33         finally
    34         {
    35             JDBCHelper.disposeConnect(pst, conn);
    36         }
    37     }
    View Code

           2. 使用statement实例对多条脚本进行提交(只提交一次,但无法进行预编译sql脚本)

     1     @Test
     2     public void testTransaction() throws Exception
     3     {
     4         Connection conn = null;
     5         Statement st = null;
     6         PreparedStatement pst = null;
     7         try
     8         {
     9             conn = JDBCHelper.getConnection();
    10 
    11             conn.setAutoCommit(false);
    12             String sql1 = "update t_account t set t.money=t.money-100 where t.name =?";
    13             String sql2 = "update t_account t set t.money=t.money+100 where t.name =?";
    14             pst = conn.prepareStatement(sql1);
    15             // 只能批量执行某一条固定的sql语句,并且进行参数化设置
    16             pst.setString(1, "a"); // 为name 为 a的用户减少100元
    17             pst.addBatch();
    18             pst.setString(1, "b"); // 为name 为b的用户减少100元
    19             pst.addBatch();
    20             pst.executeBatch(); // 只能在执行完成以后提交一次,然后改成新的sql脚本。但容易引发内存泄漏
    21 
    22             pst = conn.prepareStatement(sql2); // 内存泄漏,存在未关闭的链接
    23             pst.setString(1, "c");
    24             pst.addBatch();
    25             pst.executeBatch();
    26             conn.commit();
    27 
    28         }
    29         catch (Exception e)
    30         {
    31             conn.rollback();
    32         }
    33         finally
    34         {
    35             JDBCHelper.disposeConnect(pst, conn);
    36         }
    37     }
    View Code

     

     

     

  • 相关阅读:
    两个排序数组的第k小——Java实现
    单向链表反转——递归与非递归实现
    白话HMM系列3——维特比算法求解隐藏序列
    白话Shell命令1——top查看Linux进程
    白话HMM系列2——Baum Welch算法的进阶
    Hadoop原理深度剖析系列1——Hadoop的基本知识
    白话HMM系列1——从一个缩略语还原的例子说起
    软件工程第二次作业
    Hello World!
    查看帐号授权信息
  • 原文地址:https://www.cnblogs.com/doucheyard/p/5643888.html
Copyright © 2020-2023  润新知