zoukankan      html  css  js  c++  java
  • JDBC中的事务-Transaction

    事务-Transaction

    某些情况下我们希望对数据库的某一操作要么整体成功,要么整体失败,经典的例子就是支付宝提现。例如我们发起了支付宝到银行卡的100元提现申请,我们希望的结果是支付宝余额减少100元,银行卡余额增加100元,而不是支付宝的100元被扣除,而银行卡的100元却没收到。也就是说,要么100元从支付宝扣除的同时银行卡也会多出一百元,要么这次提现失败支付宝的100元还在,银行卡也没有收到钱。支付宝扣钱和银行卡收钱,这两件事要么都成功要么都失败。

     

    事物的ACID特性:

    满足ACID特性的操作,我们可以说它是一个事物。

    1. 原子性:该操作是最小逻辑单元整体,已经不可分隔。
    2. 一致性:要么所有都执行,要么所有都不执行。
    3. 隔离性:多个事务相互隔离,互不影响。
    4. 持久性:事物的执行结果永久生效。

     

    对事物的控制:

    在JDBC中可以调用Connection对象的setAutoCommit(false)这个接口,将commit()之前的所有操作都看成是一个事物。同时,如果事务执行过程中发生异常,可以调用rollback()接口进行回滚到事务开始之前的状态。

     

    示例代码:

    下面代码演示了将cjk的100元转账到ly的账户上:

    package org.lyk.main;

    import java.sql.Connection;

    import java.sql.PreparedStatement;

    import java.sql.ResultSet;

    import java.sql.SQLException;

    import org.apache.commons.dbcp2.BasicDataSource;

    public class Main

    {

           public static String DBDRIVER = "com.mysql.jdbc.Driver";

           public static String DB_URL = "jdbc:mysql://localhost:3306/mldn";

           public static String USERNAME = "root";

           public static String PASSWORD = "admin";

           public static BasicDataSource bds = null;

           public static void main(String[] args)

           {

                  dbPoolInit();

                  transferAmount();

                  System.out.println("///Done~~~");

           }

           public static void dbPoolInit()

           {

                  bds = new BasicDataSource();

                  bds.setDriverClassName(DBDRIVER);

                  bds.setUrl(DB_URL);

                  bds.setUsername(USERNAME);

                  bds.setPassword(PASSWORD);

           }

          

           public static boolean transferAmount()

           {

                  boolean retVal = true;

                 

                  String sql = "UPDATE user SET amount=? WHERE userid=?";

                  Connection conn = null;

                  PreparedStatement stmt = null;

                  ResultSet rs = null;

                 

                 

                  try

                  {

                         conn = bds.getConnection();

                         conn.setAutoCommit(false);

                         stmt = conn.prepareStatement(sql);

                         stmt.setInt(1, 0);

                         stmt.setString(2, "cjk");

                         stmt.execute();

                         stmt.setInt(1, 100);

                         stmt.setString(2, "ly");

                         stmt.execute();

                         conn.commit();

                  } catch (SQLException e)

                  {

                         // TODO Auto-generated catch block

                         e.printStackTrace();

                         try

                         {

                               conn.rollback();

                         } catch (SQLException e1)

                         {

                               // TODO Auto-generated catch block

                               e1.printStackTrace();

                         }

                  }

                  finally

                  {

                         try

                         {

                               if(conn != null)

                                      conn.close();

                               if(stmt != null)

                                      stmt.close();

                               if(rs != null)

                                      rs.close();

                         }

                         catch(Exception e)

                         {

                               //ignore all exceptions when closing...

                         }

                  }

                 

                 

                  return retVal;

           }

    }

    事务断点(Savepoint):

    某些时候,我们对一个事物操作失败,我们并不像回滚到最初状态,而是回滚到事务开始后的某一个地方,这时我们可以使用断点的方式让事物回滚到指定的断点(Savepoint)上.

    示例代码:

    下面的代码演示了如果cjk的100元转账到ly失败的话,我们将这100元转到cyx的账户上。(其中用手动跑出异常的方式模拟cjk到ly的转账失败)

    package org.lyk.main;

    import java.sql.Connection;

    import java.sql.PreparedStatement;

    import java.sql.ResultSet;

    import java.sql.SQLException;

    import java.sql.Savepoint;

    import org.apache.commons.dbcp2.BasicDataSource;

    public class Main

    {

          public static String DBDRIVER = "com.mysql.jdbc.Driver";

          public static String DB_URL = "jdbc:mysql://localhost:3306/mldn";

          public static String USERNAME = "root";

          public static String PASSWORD = "admin";

          public static BasicDataSource bds = null;

          public static void main(String[] args)

          {

                dbPoolInit();

                transferAmount();

                System.out.println("///Done~~~");

          }

          public static void dbPoolInit()

          {

                bds = new BasicDataSource();

                bds.setDriverClassName(DBDRIVER);

                bds.setUrl(DB_URL);

                bds.setUsername(USERNAME);

                bds.setPassword(PASSWORD);

          }

         

          public static boolean transferAmount()

          {

                boolean retVal = true;

               

                String sql = "UPDATE user SET amount=? WHERE userid=?";

                Connection conn = null;

                PreparedStatement stmt = null;

                ResultSet rs = null;

                Savepoint sp = null;

               

                try

                {

                      conn = bds.getConnection();

                     

                      conn.setAutoCommit(false);

                      stmt = conn.prepareStatement(sql);

                      stmt.setInt(1, 0);

                      stmt.setString(2, "cjk");

                      stmt.execute();

                      sp = conn.setSavepoint();

                     

                      stmt.setInt(1, 100);

                      stmt.setString(2, "ly");

                      stmt.execute();

                      throw new Exception();

                }

                catch (Exception e)

                {

                      e.printStackTrace();

                      try

                      {

                            conn.rollback(sp);

                            stmt.setInt(1, 100);

                            stmt.setString(2, "cyx");

                            stmt.execute();

                            conn.commit();

                      } catch (SQLException e1)

                      {

                            // TODO Auto-generated catch block

                            e1.printStackTrace();

                      }

                }

                finally

                {

                      try

                      {

                            if(conn != null)

                                  conn.close();

                            if(stmt != null)

                                  stmt.close();

                            if(rs != null)

                                  rs.close();

                      }

                      catch(Exception e)

                      {

                            //ignore all exceptions when closing...

                      }

                }

               

               

                return retVal;

          }

    }

  • 相关阅读:
    jQuery源码笔记——四
    jQuery源码笔记——三
    jQuery源码笔记——二
    深度理解作用域链和闭包
    事务的传播机制
    Jvm的运行时数据区
    SpringBoot 工程结构
    MyBatis的<if>标签判空
    Redis学习
    MyBatis调用Oracle的存储过程
  • 原文地址:https://www.cnblogs.com/kuillldan/p/5865534.html
Copyright © 2011-2022 走看看