JDBC事务自动提交机制


JDBC事务自动提交机制

 首先我们先来看一段代码:

package com.guisha.JDBC;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
/**
 * 方法描述
 * @since: 1.0.0
 * @param: 
 * @return: 
 * @author: Mr.cheng
 * @date:   2021年1月6日 21点48分
 */
public class JDBCTest_03 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            InputStream input = JDBCTest_03.class.getClassLoader().getResourceAsStream("db.properties");
            Properties property = new Properties();
            try {
                //配置文件取值复制给新变量
                property.load(input);
                String driver = property.getProperty("driver");
                String url = property.getProperty("url");
                String user = property.getProperty("user");
                String password = property.getProperty("password");
                //注册驱动
                Class.forName(driver);
                try {
                    //获取链接
                    conn = DriverManager.getConnection(url, user, password);
                    String sql = "UPDATE LOGINNAME SET NAMEPASS = ? WHERE NAME = ? ";
                    //获取数据库操作对象
                    ps = conn.prepareStatement(sql);
                    //添加sql数据
                    ps.setString(1,"guisha");
                    ps.setString(2,"Mrcheng");
                    //执行SQL语句,返回条数
                    int i = ps.executeUpdate();
                    System.out.println(i);

                    ps = conn.prepareStatement(sql);
                    ps.setString(1,"wuxin");
                    ps.setString(2,"wuxin");
                    int i1 = ps.executeUpdate();
                    System.out.println(i1);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            //关闭资源
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

  代码中,我们更新2条数据,但是在 int i = ps.executeUpdate(); 这里会自动提交事务,可以理解为提交SQL语句对数据库修改

我们需要了解JDBC的事务是自动提交的,什么是自动提交?

  1)只执行任意一条DML语句,则提交一次。JDBC默认的提交方式是自动提交,是JDBC默认的事务行为

  2)在实际开发业务中,通常都是N条DML语句共同联合才能完成的,必须保证DML语句在一个事务中同时成功或者同时失败

 

我们来看一个小例子来验证以下JDBC的事务是否是自动提交机制!

   两个人转账的小案例:

package com.guisha.JDBC;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 方法描述
 * @since: 1.0.0
 * @param:
 * @return:
 * @author: Mr.cheng
 * @date:   2021年1月6日 21点48分
 */
public class JDBCTest_04 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            InputStream input = JDBCTest_04.class.getClassLoader().getResourceAsStream("db.properties");
            Properties property = new Properties();
            try {
                //配置文件取值复制给新变量
                property.load(input);
                String driver = property.getProperty("driver");
                String url = property.getProperty("url");
                String user = property.getProperty("user");
                String password = property.getProperty("password");
                //注册驱动
                Class.forName(driver);
                try {
                    //获取链接
                    conn = DriverManager.getConnection(url, user, password);
                    String sql = "UPDATE center_cat SET user_baln = ? WHERE USER_NAME = ? ";
                    //获取数据库操作对象
                    ps = conn.prepareStatement(sql);
                    //添加sql数据
                    ps.setDouble(1,10000);
                    ps.setString(2,"小明");
                    //执行SQL语句,返回条数
                    int i = ps.executeUpdate();
                    System.out.println(i);
                    //自定义NullPointerException
                    String s = null;
                    s.toString();

                    ps.setString(1,"10000");
                    ps.setString(2,"王老头");
                    i += ps.executeUpdate();
                    System.out.println(i);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            //关闭资源
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

  运行之后会出错,我们程序中定义的 NullPointerException 

 

   再查看数据库,数据库执行一半出现异常终止,小明资金共20000,现在能够看出来 小明明学转出的10000元消失不见了,这里就是每执行一条DML语句,事务会自动提交一次

 

 

 

 

现在我们设置是为手动开启和手动提交,如果中间出现错误,我们回滚数据

代码如下:

package com.guisha.JDBC;


import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 方法描述
 * @since: 1.0.0
 * @param:
 * @return:
 * @author: Mr.cheng
 * @date:   2021年1月6日 21点48分
 */
public class JDBCTest_04 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            InputStream input = JDBCTest_04.class.getClassLoader().getResourceAsStream("db.properties");
            Properties property = new Properties();
            try {
                //配置文件取值复制给新变量
                property.load(input);
                String driver = property.getProperty("driver");
                String url = property.getProperty("url");
                String user = property.getProperty("user");
                String password = property.getProperty("password");
                //注册驱动
                Class.forName(driver);
                try {
                    //获取链接
                    conn = DriverManager.getConnection(url, user, password);
                    //开启事务
                    conn.setAutoCommit(false);
                    String sql = "UPDATE center_cat SET user_baln = ? WHERE USER_NAME = ? ";
                    //获取数据库操作对象
                    ps = conn.prepareStatement(sql);
                    //第一次给?传值
                    ps.setDouble(1,10000);
                    ps.setString(2,"小明");
                    //执行SQL语句,返回条数
                    int i = ps.executeUpdate();
                    System.out.println(i);

                    // 自定义NullPointerException 用来终止正在执行的程序,用于演示JDBC事务自动提交机制的问题
            // 想正常实执行代码,请删除自定义自定义NullPointerException异常
                    String s = null;
                    s.toString();

                    //第二次给?传值
                    ps.setString(1,"10000");
                    ps.setString(2,"王老头");
                    i += ps.executeUpdate();
                    System.out.println(i == 2 ? "转账成功!": "转账失败!");
                    //提交事务
                    conn.commit();
                } catch (SQLException e) {
/            //数据回滚
                    if (conn !=null){
                        try {
                            conn.rollback();
                        } catch (SQLException throwables) {
                            throwables.printStackTrace();
                        }
                    }
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            //关闭资源
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

  以上代码就算出错,数据会进行回滚,重点使用了conn.setAutoCommit(false)(手动开启事务)、conn.commit()(手动提交事务)和conn.rollback(手动回滚数据)

 

正常执行如下:

package com.guisha.JDBC;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 方法描述
 * @since: 1.0.0
 * @param:
 * @return:
 * @author: Mr.cheng
 * @date:   2021年1月6日 21点48分
 */
public class JDBCTest_04 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            InputStream input = JDBCTest_04.class.getClassLoader().getResourceAsStream("db.properties");
            Properties property = new Properties();
            try {
                //配置文件取值复制给新变量
                property.load(input);
                String driver = property.getProperty("driver");
                String url = property.getProperty("url");
                String user = property.getProperty("user");
                String password = property.getProperty("password");
                //注册驱动
                Class.forName(driver);
                try {
                    //获取链接
                    conn = DriverManager.getConnection(url, user, password);
                    //开启事务
                    conn.setAutoCommit(false);
                    String sql = "UPDATE center_cat SET user_baln = ? WHERE USER_NAME = ? ";
                    //获取数据库操作对象
                    ps = conn.prepareStatement(sql);
                    //第一次给?传值
                    ps.setDouble(1,10000);
                    ps.setString(2,"小明");
                    //执行SQL语句,返回条数
                    int i = ps.executeUpdate();
                    System.out.println(i);

                    //第二次给?传值
                    ps.setString(1,"10000");
                    ps.setString(2,"王老头");
                    i += ps.executeUpdate();
                    System.out.println(i == 2 ? "转账成功!": "转账失败!");
                    //提交事务
                    conn.commit();
                } catch (SQLException e) {
                    if (conn !=null){
                        try {
                            conn.rollback();
                        } catch (SQLException throwables) {
                            throwables.printStackTrace();
                        }
                    }
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            //关闭资源
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
}

  

 

 

 

上一篇:JDBC中Statement和PreparedSatement的区别和运用详情 

下一 篇:JDBC工具类的封装


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM