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