(1) Java實現JDBC連接及事務的方式


許多數據庫的auto-commit默認是ON的,比如MySQL,PostgresSQL等。當然也有默認是OFF的,比如Oracle(Oracle里面執行DML語句是需要手動commit的)。

這里我們以MySQL為例,先寫一個基本的JDBC連接的例子:

package com.mycloud.demo.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

public class ConncetionTest1 {

    public static void main(String[] args) {

        String jdbcUrl = "jdbc:mysql://localhost:3306/test_db";
        String username = "xxx";
        String password = "xxx";

        // Basic sample
        // Connection -> Statement -> ResultSet: try with resource
        try (Connection con = DriverManager.getConnection(jdbcUrl, username, password);
                Statement stmt = con.createStatement();
                ResultSet rs = stmt.executeQuery("select id, account from test")) {
            String result = getResultSetAsString(rs);
            System.out.println(result);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("Error occurred!");
        }
    }

    private static String getResultSetAsString(ResultSet rs) throws SQLException {

        ResultSetMetaData rsmd = rs.getMetaData();
        int numCols = rsmd.getColumnCount();
        StringBuilder sb = new StringBuilder();

        while (rs.next()) {
            for (int i = 1; i <= numCols; i++) {
                String elem = rs.getString(i);
                if (rs.wasNull())
                    sb.append("NULL");
                else
                    sb.append(elem);

                if (i != numCols)
                    sb.append("|");
            }
            sb.append(System.lineSeparator());
        }

        return sb.toString();
    }
}

 

在auto-commit默認是ON的情況下,每一條sql都是一個獨立的事務,運行完直接commit。但是如果需要實現事務,比如我們執行一組DML,如果某一條失敗,就全部rollback。這種方式就不行了:

        try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
                Statement stmt = conn.createStatement()) {
            stmt.execute("INSERT INTO test(id, account) VALUES (1, 100)");
            stmt.execute("INSERT INTO test(id, account) VALUES (2, 200)");
            stmt.execute("INSERT INTO test(id, account) VALUES (2, 201)"); // Exception: duplicate pk
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("Error occurred!");
        }

我們查詢數據庫發現,成功插入了兩條數據:

id account
1 100
2 200

 

 

 

 

在這種情況下,我們首先要通過設置connection.setAutoCommit為OFF來開啟事務,再通過connection.commit/connection.rollback來提交/回滾事務。 

        try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
                Statement stmt = conn.createStatement()) {

            conn.setAutoCommit(false);
            try {
                stmt.execute("INSERT INTO test(id, account) VALUES (1, 100)");
                stmt.execute("INSERT INTO test(id, account) VALUES (2, 200)");
                stmt.execute("INSERT INTO test(id, account) VALUES (3, 300)");
            } catch (SQLException e) {
                e.printStackTrace();
                conn.rollback(); // rollback
                throw e;
            }
            conn.commit(); // commit

        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("Error occurred!");
        }

我們查詢數據庫發現,成功插入了3條數據:

id account
1 100
2 200
3 300

 

 

 

 

 

當然,如果我們去掉conn.commit()這一句,數據就不會插入了。

如果這一組DML中某一條失敗,則會被SQLException捕獲,從而拋出異常並回滾。

        try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
                Statement stmt = conn.createStatement()) {

            conn.setAutoCommit(false);
            try {
                stmt.execute("INSERT INTO test(id, account) VALUES (1, 100)");
                stmt.execute("INSERT INTO test(id, account) VALUES (2, 200)");
                stmt.execute("INSERT INTO test(id, account) VALUES (2, 201)"); // Exception: duplicate pk
                stmt.execute("INSERT INTO test(id, account) VALUES (3, 300)");
            } catch (SQLException e) {
                e.printStackTrace();
                conn.rollback(); // rollback
                throw e;
            }
            conn.commit(); // commit

        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("Error occurred!");
        }

我們再查詢數據庫發現,並沒有數據插入。


免責聲明!

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



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