JDBC事務相關方法簡介
本文將借助示例,簡單講解下JDBC操作Pg事務的流程。
首先來簡單講解下事務的定義:為了確保兩個(多個)數據庫操作都生效,或者兩個操作都不發生,可以使用事務。根據定義,事務是作為單個單元執行的一組語句。換句話說,要么所有語句都成功執行,要么沒有執行。
禁用自動提交模式
當建立與PostgreSQL數據庫的連接時,它處于自動提交模式。這意味著每個SQL語句都被視為事務并自動提交。
如果要在事務中封裝一個或多個語句,則必須禁用自動提交模式。為此,我們可以調用Connection.setAutoCommit()
方法來修改SQL提交模式:
Connection.setAutoCommit(false);
最佳做法是僅對事務模式禁用自動提交模式。它避免為多個語句保留數據庫鎖。
提交事務
要提交事務,請調用Connection對象的commit方法,如下所示:
Connection.commit();
當調用commit()
方法,所有前面的SQL語句作為一個單元一起提交。
回滾事務
既然使用了事務,那我們肯定會有回滾的時候,我們可以使用rollback()
方法來中止當前事務并將值恢復為原始值。
Connection.rollback();
PostgreSQL JDBC 事務示例
讓我們舉一個使用JDBC API執行PostgreSQL事務的示例。
首先,創建一個表示ProRank的實體類,如下所示:
import lombok.Data; @Data public class ProRank { Integer id; String name; String team; String line; Integer rank; }
然后,編寫以下代碼,供我們測試事務操作。
import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.sql.*; @SpringBootTest class JdbcTrasationTests { private final String url = "jdbc:p6spy:postgresql://localhost:5432/postgres"; private final String user = "postgres"; private final String password = "112233"; /** * 連接PostgreSql數據庫 * * @return Connection * @throws SQLException */ public Connection connect() throws SQLException { return DriverManager.getConnection(url, user, password); } @Test void testTrasation() { ProRank proRank = new ProRank(); proRank.setLine("Mid"); proRank.setName("Faker"); proRank.setTeam("T1"); proRank.setRank(0); //調用 addProAndUpdateRank(proRank,2222); } /** * 關閉一個AutoCloseable對象 * * @param closeable */ private void close(AutoCloseable closeable) { try { if (closeable != null) { closeable.close(); } } catch (Exception e) { System.out.println(e.getMessage()); } } /** * 插入一條選手記錄,更新他的rank值 * * @param proRank * @param rank */ public void addProAndUpdateRank(ProRank proRank, Integer rank) { Connection conn = null; PreparedStatement pstmt = null; PreparedStatement pstmt2 = null; ResultSet rs = null; // 插入一條數據 String SQL = "INSERT INTO pro_rank(name,team,line,rank) VALUES(?,?,?,?)"; // 更新他的rank值 String SQLUpdateRank = "UPDATE pro_rank SET rank = ? WHERE id = ?;"; int id = 0; try { // 鏈接數據庫 conn = connect(); conn.setAutoCommit(false); // 插入一條數據 pstmt = conn.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS); pstmt.setString(1, proRank.getName()); pstmt.setString(2, proRank.getTeam()); pstmt.setString(3, proRank.getLine()); pstmt.setInt(4, proRank.getRank()); int affectedRows = pstmt.executeUpdate(); // 判斷是否生效 if (affectedRows > 0) { // 獲取返回的id rs = pstmt.getGeneratedKeys(); if (rs.next()) { id = rs.getInt(1); if (id > 0) { pstmt2 = conn.prepareStatement(SQLUpdateRank); pstmt2.setInt(2, id); pstmt2.setInt(1, rank); pstmt2.executeUpdate(); } } } else { // 如果新增數據失敗,回滾 conn.rollback(); } // 提交事務 conn.commit(); System.out.println("插入選手數據成功!更新選手rank成功,數據id:" + id); } catch (SQLException sqlException) { System.out.println(sqlException.getMessage()); sqlException.printStackTrace(); // 回滾事務 System.out.println("回滾事務..."); try { if (conn != null) { conn.rollback(); } } catch (SQLException e) { System.out.println(e.getMessage()); e.printStackTrace(); } } finally { close(rs);close(pstmt);close(pstmt2);close(conn); } } }
讓我們看一下上面的代碼,他包含三個方法
connect()
?方法建立與數據庫連接,并返回連接對象。
close()
?方法關閉數據庫操作可關閉的對象,如Resultset、Statement和Connection。
addProAndUpdateRank()
方法插入新的選手,并在事務中更新選手的rank字段。此方法包含邏輯如下:
- 首先,在
pro_rank
表中插入一條新的選手數據。 - 接下來,獲取新插入的選手數據的id
- 然后,更新插入選手的rank值。
- 之后,如果步驟2和3均成功,則提交事務。否則,回滾事務
- 最后,關閉ResultSet、PreparedStatement和Connection對象。
如果我們在第一個場景中執行程序,我們會得到以下結果:
插入選手數據成功!更新選手rank成功,數據id:14
我們可以通過查詢pro_rank
表格,來查看上述代碼執行結果:
SELECT * FROM "public"."pro_rank" LIMIT 1000 OFFSET 0;
現在,讓我們測試一下事務回滾的情況,比如,我們可以在插入一條數據的時候,將name字段賦值為超出數據庫長度的字串,運行程序結果如下:
ERROR: value too long for type character varying(7)
事務將回滾,并且沒有任何內容插入pro_rank表
以上就是PostgreSql JDBC事務操作方法詳解的詳細內容,更多關于PostgreSql JDBC事務操作的資料請關注其它相關文章!