JDBC | 第四章: JDBC之Transaction事務提交與回滾


默認情況下,當我們創建一個數據庫連接時,會運行在自動提交模式(Auto-commit)下。這意味着,任何時候我們執行一條SQL完成之后,事務都會自動提交。所以我們執行的每一條SQL都是一個事務,並且如果正在運行DML或者DDL語句,這些改變會在每一條SQL語句結束的時存入數據庫。有時候我們想讓一組SQL語句成為事務的一部分,那樣我們就可以在所有語句運行成功的時候提交,並且如果出現任何異常,這些語句作為事務的一部分,我們可以選擇將其全部回滾。

讓我們通過一個簡單的示例理解一下,這里使用JDBC的事務管理來支持數據的完整性

 /*
     * 發生異常回滾所有執行更新的sql
     * */
    public void insrolledAll() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        PreparedStatement preparedStatement1 = null;
        //這里參數用?占位符表示
        String sqlTeacher = "insert into teacher ( name, age, hobby, addr) values (?,?,?,?)";
        String sqlStudent = "insert into student (name, age, addr, hobby) values (?,?,?,?)";
        try {
            //獲取數據連接
            connection = basicUse.getConnection();
            //設置事務自動提交為手動提交
            connection.setAutoCommit(false);

            //獲取發送sql指令執行sql進行預編譯
            preparedStatement = connection.prepareStatement(sqlStudent);

            //設置sql語句參數索引從1開始
            preparedStatement.setObject(1, "Tom");
            preparedStatement.setObject(2, 24);
            preparedStatement.setObject(3, "上海");
            preparedStatement.setObject(4, "籃球");
            preparedStatement.executeUpdate();
            System.out.println("執行sqlStudent" + sqlStudent);

            //手動制造異常
            int i = 10 / 0;

            preparedStatement1 = connection.prepareStatement(sqlTeacher);
            preparedStatement1.setObject(1, "kenx");
            preparedStatement1.setObject(2, 24);
            preparedStatement1.setObject(3, "足球");
            preparedStatement1.setObject(4, "北京");
            preparedStatement1.executeUpdate();
            System.out.println("執行sqlTeacher" + sqlTeacher);

            //提交事務
            connection.commit();

        } catch (Exception e) {
            //回滾事務
            try {
                connection.rollback();
                System.out.println("JDBC Transaction rolled back successfully");
            } catch (SQLException e1) {
                System.out.println("SQLException in rollback" + e1.getMessage());
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            //執行完數據庫操作后記得關閉數據庫連接資源
            try {
                preparedStatement.close();
                preparedStatement1.close();
                connection.close();

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

        }

    }

JDBC Savepoint示例

有時候一個事務可能是一組復雜的語句,因此可能想要回滾到事務中某個特殊的點。JDBC Savepoint幫我們在事務中創建檢查點(checkpoint),這樣就可以回滾到指定點。當事務提交或者整個事務回滾后,為事務產生的任何保存點都會自動釋放並變為無效。把事務回滾到一個保存點

 /*
     * 發生異常回滾到指定的位置
     * */
    public void insrolledSavepoint() {
        Savepoint savepoint = null;
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        PreparedStatement preparedStatement1 = null;
        //這里參數用?占位符表示
        String sqlTeacher = "insert into teacher ( name, age, hobby, addr) values (?,?,?,?)";
        String sqlStudent = "insert into student (name, age, addr, hobby) values (?,?,?,?)";
        try {
            //獲取數據連接
            connection = basicUse.getConnection();
            //設置事務自動提交為手動提交
            connection.setAutoCommit(false);

            //獲取發送sql指令執行sql進行預編譯
            preparedStatement = connection.prepareStatement(sqlStudent);

            //設置sql語句參數索引從1開始
            preparedStatement.setObject(1, "JDBC");
            preparedStatement.setObject(2, 24);
            preparedStatement.setObject(3, "上海");
            preparedStatement.setObject(4, "籃球");
            preparedStatement.executeUpdate();
            System.out.println("執行sqlStudent" + sqlStudent);


            //設置回滾的點  失敗只會回滾老師信息
            savepoint = connection.setSavepoint("teacher");

            preparedStatement1 = connection.prepareStatement(sqlTeacher);
            preparedStatement1.setObject(1, "kenx");
            preparedStatement1.setObject(2, 24);
            preparedStatement1.setObject(3, "足球");
            preparedStatement1.setObject(4, "北京");
            preparedStatement1.executeUpdate();
            System.out.println("執行sqlTeacher" + sqlTeacher);

               //手動制造異常
               int i = 10 / 0;
            //提交事務
            connection.commit();


        } catch (Exception e) {
            //回滾事務
            try {
                if (StrUtil.isEmptyIfStr(savepoint)) {
                    //回滾所有更新sql
                    connection.rollback();
                    System.out
                            .println("JDBC Transaction rolled back successfully");
                } else {
                    connection.rollback(savepoint);
                    System.out.println("JDBC Transaction rolled back successfully");
                    connection.commit();
                }

            } catch (SQLException e1) {
                System.out.println("SQLException in rollback" + e1.getMessage());
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            //執行完數據庫操作后記得關閉數據庫連接資源
            try {
                preparedStatement.close();
                preparedStatement1.close();
                connection.close();

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

        }

    }

完整項目案例
點擊這里 github


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM