自己写架构笔记(4)----JDBC如何利用事务去处理sql语句

1、JDBC中的事务

最简单的事务的概念的总结

在一个方法中,同时存在多条更新类语句(insert delelte update),那么这些语句需要以整体方式执行,要么都成功,要么都失败,不可以拆分执行。
举一个很简单的例子,A和B两个人,A从B中购买东西,A需要向B支付一定的费用,假如A、B各有9000元,A需要向B支付5000元,B需要收入5000元,这两个操作就包含在一个事务之中,两个操作需要以整体方式执行,不可以拆分,要么都成功,要么都失败,绝不允许只有A支付了,B没有收到的这样的情况。

事务的四个特性

1、一致性:
事务在执行前后,数据的大小总和保持不变。
也就是在上面的例子中的A在支付前后,A和B的总金额都是18000,绝对不允许在这个事务执行之后,这个数据的总和发生改变。
2、原子性
构成事务的语句,以整体方式执行,要么都成功,要么都失败。
3、持久性
事务做出的改变,一经确认,具有永久时效性,不可以再撤回。
4、隔离性
事务执行期间,涉及的数据暂时处于锁定的状态,其他事务不能处理.
事务的隔离性在数据库底层是通过锁机制完成的.
隔离性就好比java线程中的两个线程不可以同时去修改一个数据,必须加上互斥锁这样的锁,才能保证隔离性。

2、JDBC中采用事务的方式来执行sql语句

我们假定有两个人,“武松”和“西门吹雪”两个人做生意,后者需要向前者支付5000元,假定两个人都有9000,我们在这里偷偷的给武松的金钱的数据类型大小,设置成4位的,也就是不会超过9999,意思就是,就算收到了5000,也不会加进来称为自己的钱,那么这个时候,我们再看西门吹雪是不是成功支付了,还是没有成功呢?我们根据事务的原子性和一致性,也知道,是不会成功的,具体看一下代码:
先看一下和数据库有关的DBUtils类:

package com.neusoft.system.db;

import java.sql.*;
//资源文件解析器
import java.util.ResourceBundle;


public class DBUtils 
{
//1.定义驱动串---整个驱动jar包中,核心类的路径
private static String driver=null;
//2.定义链接串---数据库所在的位置及名称
private static String url=null;
private static String userName=null;
private static String password=null;

/**
 * 静态块
 * 在类被第一次加载入内存时候,执行,以后不再执行
 */
static
{
    System.out.println("run static .......");
    try
    {
        //获取资源文件解析器实例
        ResourceBundle bundle=ResourceBundle.getBundle("DBOPtions");
        //从资源文件获取数据
        driver=bundle.getString("DRIVER");
        url=bundle.getString("URL");
        userName=bundle.getString("USERNAME");
        password=bundle.getString("PASSWORD");

        //3.加载驱动
        Class.forName(driver);
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}   

/**
 * 当一个类中所有的成员(属性和方法)都是static,那么此时构造器应该私有
 */
private DBUtils() {}


public static Connection getConnection()throws Exception
{
    //4.创建链接
    Connection conn=DriverManager.getConnection(url, userName, password);
    return conn;
}






public static void close(PreparedStatement pstm)
{
    try
    {
        if(pstm!=null)
        {
            pstm.close();
        }
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}

public static void close(Connection conn)
{
    try
    {
        if(conn!=null && !conn.isClosed())
        {
            conn.close();
        }
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}

public static void main(String[] args) 
{
    try
    {
        System.out.println(DBUtils.getConnection());                    
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}

}

事务的方式来执行更新操作:

package transaction;

import java.sql.*;
import com.neusoft.system.db.DBUtils;

public class Person 
{

public static void main(String[] args)
{
    try 
    {
        boolean tag=Person.tiger();
        System.out.println(tag);

    }
    catch (Exception e) 
    {
        e.printStackTrace();
    }
}

private static boolean tiger()throws Exception
{
    //1.定义JDBC接口
    Connection conn=null;
    PreparedStatement pstm1=null;   //扣减西门吹雪
    PreparedStatement pstm2=null;   //增加武松
    try
    {
        //2.创建连接
        conn=DBUtils.getConnection();

        //3.完成对西门吹雪账户的处理
        //3.1定义SQL语句
        String sql1="update person set umoney=umoney-? where uid=?";
        //3.2编译SQL语句
        pstm1=conn.prepareStatement(sql1);
        pstm1.setObject(1, 5);
        pstm1.setObject(2, 2);

        //4.处理武松的账户
        //4.1定义SQL语句
        String sql2="update person set umoney=umoney+? where uid=?";
        //4.2编译SQL及赋值
        pstm2=conn.prepareStatement(sql2);
        pstm2.setObject(1, 5);
        pstm2.setObject(2, 1);


        //5.以事务方式执行SQL
        //5.1定义事务返回值
        boolean tag=false;
        /**
         * 5.2开启事务
         * conn内部存在一个叫autoCommit的属性,该属性默认值为true,
         * 表示遇到更新类语句,立即修改数据库
         * setAutoCommit(false);  遇到更新类语句,先不要修改数据库,而是进行彩排(模拟执行),
         * 等待后继指令,后继指令如果是更新数据库那么再去更新,如果是撤销,那么取消更新操作
         */
        conn.setAutoCommit(false);
        try
        {
            //5.3在事务内部执行所有的更新语句
            pstm1.executeUpdate();
            pstm2.executeUpdate();

            //5.4.1:确认对数据的修改---提交事务
            conn.commit();
            //5.5修改事务返回值,表示执行成功
            tag=true;
        }
        catch(Exception ex)
        {
            //5.4.2:取消对数据的修改---事务回滚
            conn.rollback();
            ex.printStackTrace();
        }
        finally
        {
            //5.6结束事务
            conn.setAutoCommit(true);
        }
        return tag;

    }
    finally
    {
        DBUtils.close(pstm1);
        DBUtils.close(pstm2);
        DBUtils.close(conn);
    }
}



}

【注】
事务不提交,不会执行sql语句。
在捕捉到异常的时候,要进行事务的回滚,这样才不会出差错。
JDBC结束之后,一定记得关闭连接资源,否则内存泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值