0Pricing
Java Academy · บทเรียน

ธุรกรรม

ยืนยันและย้อนกลับ

ธุรกรรม เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

ธุรกรรมคืออะไร

ธุรกรรมจะจัดกลุ่มการดำเนินการกับฐานข้อมูลหลายรายการให้เป็นหน่วยเดียวที่ต้องสำเร็จทั้งหมดหรือไม่สำเร็จเลย

คำสั่งทุกคำสั่งต้องทำงานสำเร็จและการเปลี่ยนแปลงถูกทำให้ถาวร (ยืนยันการเปลี่ยนแปลง) หรือหากมีสิ่งใดล้มเหลว การเปลี่ยนแปลงทั้งหมดจะถูกยกเลิก (ย้อนกลับ) วิธีนี้ช่วยให้ฐานข้อมูลยังคงสอดคล้องกัน

ACID ในหนึ่งนาที

ธุรกรรมมีการรับประกันตามหลัก ACID:

  • ความเป็นอะตอม — สำเร็จทั้งหมดหรือไม่สำเร็จเลย
  • ความสอดคล้อง — เปลี่ยนฐานข้อมูลจากสถานะที่ถูกต้องหนึ่งสถานะไปเป็นอีกสถานะที่ถูกต้อง
  • การแยกออกจากกัน — ธุรกรรมที่ทำงานพร้อมกันจะไม่ทำให้ข้อมูลของกันและกันเสียหาย
  • ความคงทน — เมื่อยืนยันการเปลี่ยนแปลงแล้ว การเปลี่ยนแปลงนั้นจะยังคงอยู่แม้ระบบขัดข้อง

โหมดการยืนยันอัตโนมัติ

โดยค่าเริ่มต้น การเชื่อมต่อของระบบเชื่อมต่อฐานข้อมูล Java จะทำงานในโหมดการยืนยันอัตโนมัติ: ทุกคำสั่งเป็นธุรกรรมของตัวเองและได้รับการยืนยันการเปลี่ยนแปลงทันที

วิธีนี้เหมาะกับคำสั่งเดียว แต่ใช้ไม่ได้เมื่อการเขียนข้อมูลหลายรายการต้องสำเร็จไปพร้อมกัน หากต้องการควบคุมธุรกรรมด้วยตนเอง ให้ปิดการยืนยันอัตโนมัติ

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/bank";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
            System.out.println("Default auto-commit: " + conn.getAutoCommit());
            conn.setAutoCommit(false);
            System.out.println("Now manual: " + conn.getAutoCommit());
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

การยืนยันและการย้อนกลับ

เมื่อปิดการยืนยันอัตโนมัติแล้ว คุณจะเป็นผู้กำหนดขอบเขตเอง:

  • conn.commit() ทำให้การเปลี่ยนแปลงที่รอดำเนินการทั้งหมดเป็นการเปลี่ยนแปลงถาวร
  • conn.rollback() ยกเลิกการเปลี่ยนแปลงเหล่านั้น

ตัวอย่างคลาสสิกคือการโอนเงิน: หักเงินจากบัญชีหนึ่งและเพิ่มเงินเข้าบัญชีอีกบัญชีหนึ่ง ทั้งสองรายการต้องเกิดขึ้นพร้อมกัน หรือไม่เกิดขึ้นเลย

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/bank";
        String debit = "UPDATE account SET balance = balance - ? WHERE id = ?";
        String credit = "UPDATE account SET balance = balance + ? WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
            conn.setAutoCommit(false);
            try (PreparedStatement d = conn.prepareStatement(debit);
                 PreparedStatement c = conn.prepareStatement(credit)) {
                d.setInt(1, 100); d.setInt(2, 1); d.executeUpdate();
                c.setInt(1, 100); c.setInt(2, 2); c.executeUpdate();
                conn.commit();
                System.out.println("Transfer committed");
            } catch (SQLException ex) {
                conn.rollback();
                System.out.println("Rolled back: " + ex.getMessage());
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

รูปแบบการย้อนกลับเมื่อเกิดความล้มเหลว

โครงสร้างที่ควรจำมีดังนี้:

  • ปิดการยืนยันอัตโนมัติ
  • ทำงานภายใน try ชั้นใน
  • เมื่อสำเร็จ ให้เรียก commit()
  • ใน catch ให้เรียก rollback() แล้วส่งต่อข้อผิดพลาดเดิมหรือบันทึกลงระบบ

หากไม่ย้อนกลับ ความล้มเหลวอาจทำให้ฐานข้อมูลถูกปรับปรุงไปเพียงครึ่งเดียว

จำลองความเป็นอะตอม

นี่คือแนวคิดการทำงานแบบสำเร็จทั้งหมดหรือไม่สำเร็จเลย ซึ่งจำลองด้วย Java แบบเรียบง่ายเพื่อให้ทำงานได้โดยลำพัง เราใช้การปรับปรุงสองรายการกับภาพสถานะ หากรายการใดรายการหนึ่งล้มเหลว เราจะคืนค่าภาพสถานะนั้น

public class Main {
    public static void main(String[] args) {
        int[] balances = {500, 300};
        int[] backup = balances.clone();
        try {
            balances[0] -= 200;
            if (balances[0] < 0) throw new IllegalStateException("insufficient funds");
            balances[1] += 200;
            System.out.println("Commit: " + balances[0] + ", " + balances[1]);
        } catch (RuntimeException e) {
            balances = backup;
            System.out.println("Rollback: " + balances[0] + ", " + balances[1]);
        }
    }
}

จุดบันทึก

จุดบันทึกคือตัวทำเครื่องหมายภายในธุรกรรม คุณสามารถย้อนกลับไปยังจุดนั้นได้โดยไม่ต้องยกเลิกธุรกรรมทั้งหมด

  • Savepoint sp = conn.setSavepoint()
  • conn.rollback(sp) จะยกเลิกเฉพาะงานที่เกิดขึ้นหลังจุดนั้น

มีประโยชน์สำหรับการกู้คืนบางส่วนในธุรกรรมที่ใช้เวลานาน

ระดับการแยกธุรกรรม

การแยกธุรกรรมจะควบคุมว่าธุรกรรมหนึ่งมองเห็นงานที่ยังไม่ได้ยืนยันการเปลี่ยนแปลงของอีกธุรกรรมหนึ่งได้มากน้อยเพียงใด ระบบเชื่อมต่อฐานข้อมูล Java กำหนดระดับผ่าน conn.setTransactionIsolation(...):

  • TRANSACTION_READ_COMMITTED — ค่าเริ่มต้นที่ใช้กันทั่วไป
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE — แข็งแกร่งที่สุดและช้าที่สุด

การแยกธุรกรรมในระดับสูงช่วยป้องกันความผิดปกติ แต่ลดการทำงานพร้อมกัน

ความผิดปกติในการอ่าน

การแยกธุรกรรมในระดับต่ำอาจทำให้เกิดสิ่งต่อไปนี้:

  • การอ่านข้อมูลสกปรก — มองเห็นการเปลี่ยนแปลงที่อีกธุรกรรมหนึ่งยังไม่ได้ยืนยัน
  • การอ่านซ้ำไม่ได้ — แถวข้อมูลเปลี่ยนแปลงระหว่างการอ่านสองครั้ง
  • การอ่านข้อมูลแฝง — มีแถวข้อมูลใหม่ปรากฏขึ้นและตรงกับคำค้นหาก่อนหน้า

เลือกระดับต่ำที่สุดที่ยังป้องกันความผิดปกติซึ่งตรรกะของคุณยอมรับไม่ได้

คืนค่าการยืนยันอัตโนมัติ

หากคุณยืมการเชื่อมต่อมาจากพูล ให้คืนค่าเดิมก่อนส่งการเชื่อมต่อนั้นกลับไป

หลังจากทำธุรกรรมด้วยตนเองแล้ว ให้เรียก conn.setAutoCommit(true) อีกครั้ง (หรือคืนค่าเป็นค่าที่ตรวจพบขณะยืม) เพื่อไม่ให้ผู้ใช้คนถัดไปประหลาดใจกับการตั้งค่าของคุณ

ทำธุรกรรมให้สั้น

ธุรกรรมจะถือล็อกไว้จนกว่าจะยืนยันการเปลี่ยนแปลงหรือย้อนกลับ ธุรกรรมที่ใช้เวลานานจะขัดขวางงานอื่นและเพิ่มความเสี่ยงต่อภาวะชะงักงัน

  • อย่าดำเนินการติดต่อเครือข่ายที่ช้าหรือรอการป้อนข้อมูลจากผู้ใช้ภายในธุรกรรมที่เปิดอยู่
  • รวบรวมข้อมูลให้เสร็จก่อน จากนั้นจึงเปิดการเชื่อมต่อ เขียนข้อมูล และยืนยันการเปลี่ยนแปลงอย่างรวดเร็ว

ธุรกรรมที่สั้นและมุ่งเน้นเฉพาะงานจะรองรับการขยายระบบได้ดีกว่ามาก

ตรวจสอบอย่างรวดเร็ว

การเรียก connection.rollback() มีผลอย่างไร

สรุปทบทวน

ธุรกรรมช่วยให้คุณมั่นใจในความปลอดภัยแบบสำเร็จทั้งหมดหรือไม่สำเร็จเลย:

  • ปิดการยืนยันอัตโนมัติด้วย setAutoCommit(false)
  • เรียก commit() เมื่อสำเร็จ และเรียก rollback() เมื่อเกิดความล้มเหลว
  • ใช้จุดบันทึกสำหรับการย้อนกลับบางส่วน
  • ปรับระดับการแยกธุรกรรมเพื่อสร้างสมดุลระหว่างความถูกต้องและการทำงานพร้อมกัน
  • คืนค่าการยืนยันอัตโนมัติก่อนส่งการเชื่อมต่อในพูลกลับไป

คำถามที่พบบ่อย

บทเรียน “ธุรกรรม” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ธุรกรรม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ธุรกรรม”

ยืนยันและย้อนกลับ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ธุรกรรม” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน JDBC
  2. PreparedStatement
  3. ธุรกรรม
  4. การรวมการเชื่อมต่อด้วย HikariCP
← กลับไปที่ Java Academy