IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java操作数据库(三,趣味理解JDBC事务) -> 正文阅读

[Java知识库]Java操作数据库(三,趣味理解JDBC事务)

如果读者对此篇文章有不解可以查看小编JDBC分区下的文章哦,欢迎大家点赞与收藏!

目录

?事务

事务的讲解小编准备从一个故事进行讲起:

创建一个银行(数据库创建,张三:100000,小明:0)

?模拟银行交易(jdbc模拟)

突然发生意外了,程序收钱了,但没有转账给小明?

第一种情况(时间上有延迟,转账后几分钟到)

?第二种情况 程序内部出现问题(钱没了)

结论(记住)

解决办法(在实际开发中,把JDBC的自动提交机制关闭,改为手动提交,三步骤)

第一,先把事务改成手动提交(setAutoCommit(false))

第二,手动提交,关闭事务(commit())

第三步,出现问题,程序进行回滚(rollback())

完整代码


?事务

事务的讲解小编准备从一个故事进行讲起:

话说在很久很久以前发生这样一个故事,地主张三在银行门口打钱给自己儿子小明,自己账户上有100000元,小明没有钱,张三打了50000给儿子,然后就发生了下面这样的事。

创建一个银行(数据库创建,张三:100000,小明:0)

create table t_bank(
	 id int primary key auto_increment ,
	 u_name varchar(20) not null ,
 	 money double(10,2)
-- 10是有效数子,2是小数的位数  
);
insert into t_bank(u_name , money) value ("zhangsan",100000);
insert into t_bank (u_name,money) value ("xiaoming",0);
select * from t_bank;

?模拟银行交易(jdbc模拟)

package com.luosf.jdbc;

import java.sql.*;


/**
模拟银行转账

 */
public class Jdbc_Transfer {
    public static void main(String[] args) {
            transfer();
    }
    static void transfer(){
        Connection conn = null;
        PreparedStatement prestat = null;
        ResultSet res = null;


        try {
            //1,创建驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2,链接数据库
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3333/db_nhjc?charset=utf-8","root","root");

            //3,获取预编译数据库操作对象
            String sql = "update t_bank set money = ? where u_name = ? ";


            //此时发送sql语句给DBMS,进行sql语句的编译
             prestat = conn.prepareStatement(sql);

             //张三给小明转账
             prestat.setDouble(1,50000);
             prestat.setString(2,"zhangsan");

             int count = prestat.executeUpdate();//跟新数据库,当跟新完成后,count+1;

             //小明账户到账
            prestat.setDouble(1,50000);
            prestat.setString(2,"xiaoming");
            count += prestat.executeUpdate();  //再次更新,count+1,count=2

            System.out.println(count == 2 ? "转账成功" : "转账失败");




        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放资源
            if (res != null){
                try {
                    res.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (prestat != null){
                try {
                    prestat.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

这样就转账完成了

突然发生意外了,程序收钱了,但没有转账给小明?

第一种情况(时间上有延迟,转账后几分钟到)

张三给小明打电话,我钱打给你了,你看看,小明一看,我靠,明没钱这个月要吃土了!

实现

 Thread.sleep(20000); //休息20秒,模拟断电了

看看

package com.luosf.jdbc;

import java.sql.*;


/**
模拟银行转账

 */
public class Jdbc_Transfer {
    public static void main(String[] args) {
            transfer();
    }
    static void transfer(){
        Connection conn = null;
        PreparedStatement prestat = null;
        ResultSet res = null;


        try {
            //1,创建驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2,链接数据库
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3333/db_nhjc?charset=utf-8","root","root");

            //3,获取预编译数据库操作对象
            String sql = "update t_bank set money = ? where u_name = ? ";


            //此时发送sql语句给DBMS,进行sql语句的编译
             prestat = conn.prepareStatement(sql);

             //张三给小明转账
             prestat.setDouble(1,50000);
             prestat.setString(2,"zhangsan");

             int count = prestat.executeUpdate();//跟新数据库,当跟新完成后,count+1;

            Thread.sleep(20000); //休息20秒,模拟断电了
            //小明账户到账
            prestat.setDouble(1,50000);
            prestat.setString(2,"xiaoming");
            count += prestat.executeUpdate();  //再次更新,count+1,count=2

            System.out.println(count == 2 ? "转账成功" : "转账失败");




        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放资源
            if (res != null){
                try {
                    res.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (prestat != null){
                try {
                    prestat.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

?第二种情况 程序内部出现问题(钱没了)

    String s = null;
    s.toString();//创建空指针异常
package com.luosf.jdbc;

import java.sql.*;


/**
模拟银行转账

 */
public class Jdbc_Transfer {
    public static void main(String[] args) {
            transfer();
    }
    static void transfer(){
        Connection conn = null;
        PreparedStatement prestat = null;
        ResultSet res = null;


        try {
            //1,创建驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2,链接数据库
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3333/db_nhjc?charset=utf-8","root","root");

            //3,获取预编译数据库操作对象
            String sql = "update t_bank set money = ? where u_name = ? ";


            //此时发送sql语句给DBMS,进行sql语句的编译
             prestat = conn.prepareStatement(sql);

             //张三给小明转账
             prestat.setDouble(1,50000);
             prestat.setString(2,"zhangsan");

             int count = prestat.executeUpdate();//跟新数据库,当跟新完成后,count+1;

//            Thread.sleep(20000); //休息20秒,模拟断电了
            String s = null;
            s.toString();//创建空指针异常
            //小明账户到账
            prestat.setDouble(1,50000);
            prestat.setString(2,"xiaoming");
            count += prestat.executeUpdate();  //再次更新,count+1,count=2

            System.out.println(count == 2 ? "转账成功" : "转账失败");




        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放资源
            if (res != null){
                try {
                    res.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (prestat != null){
                try {
                    prestat.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

?

结论(记住)

JDBC默认情况下是支持自动进行提交的JDBC执行一条语句就提交一次。(自动提交:执行一条DML,就自动提交一次)

解决办法(在实际开发中,把JDBC的自动提交机制关闭,改为手动提交,三步骤)

进行完一个完整的事务后,全部再一起提交。

第一,先把事务改成手动提交(setAutoCommit(false))

?

?

应该在获取链接对象后,就关闭自动提交机制

//开启事务,将自动提交改变成手动提交
 conn.setAutoCommit(false);

第二,手动提交,关闭事务(commit())

 //当前面的代码都没有问题,能执行到这,commit()关闭事务,手动提交
 conn.commit();

第三步,出现问题,程序进行回滚(rollback())

回滚:简单理解就是倒退,返回最初始的状态

//出现异常,保证安全性,程序进行回滚 
try {
       if (conn != null){
             //防止conn出现空指针异常,先进行判断一下
              conn.rollback();
             }
     }

完整代码

package com.luosf.jdbc;

import java.sql.*;


/**
模拟银行转账

 */
public class Jdbc_Transfer {
    public static void main(String[] args) {
            transfer();
    }
    static void transfer(){
        Connection conn = null;
        PreparedStatement prestat = null;
        ResultSet res = null;


        try {
            //1,创建驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2,链接数据库
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3333/db_nhjc?charset=utf-8","root","root");

            //开启事务,将自动提交改变成手动提交
            conn.setAutoCommit(false);
            //3,获取预编译数据库操作对象
            String sql = "update t_bank set money = ? where u_name = ? ";


            //此时发送sql语句给DBMS,进行sql语句的编译
             prestat = conn.prepareStatement(sql);

             //张三给小明转账
             prestat.setDouble(1,50000);
             prestat.setString(2,"zhangsan");

             int count = prestat.executeUpdate();//跟新数据库,当跟新完成后,count+1;

//            Thread.sleep(20000); //休息20秒,模拟断电了
            String s = null;
            s.toString();//创建空指针异常
            //小明账户到账
            prestat.setDouble(1,50000);
            prestat.setString(2,"xiaoming");
            count += prestat.executeUpdate();  //再次更新,count+1,count=2

            System.out.println(count == 2 ? "转账成功" : "转账失败");


            //当前面的代码都没有问题,能执行到这,commit()关闭事务,手动提交
            conn.commit();

        } catch (Exception e) {
            //出现异常,保证安全性,程序进行回滚
            try {
                if (conn != null){
                    //防止conn出现空指针异常,先进行判断一下
                    conn.rollback();
                    }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            //释放资源
            if (res != null){
                try {
                    res.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (prestat != null){
                try {
                    prestat.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

测试

?

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:35:19  更:2021-12-11 15:37:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:40:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码