数据库的事务

2024-08-30 23:04:51 浏览数 (1)

数据库的事务

事务的四个基本特性(ACID)

原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个环节。

一致性(Consistency):事务必须使数据库从一个一致的状态转移到另一个一致的状态。

隔离性(Isolation):并发执行的事务之间不会互相影响。

持久性(Durability):一旦事务提交,它对数据库的改变就是永久性的,即使系统发生故障也不会丢失。

事务的隔离级别

为了处理并发事务,数据库系统提供了不同的事务隔离级别,包括:

  • 读未提交(Read Uncommitted)
  • 读已提交(Read Committed)
  • 可重复读(Repeatable Read)
  • 串行化(Serializable)

场景描述

用户在在线购物平台上购买了一款商品,该操作涉及以下步骤:

  • 检查商品库存。
  • 更新用户购物车。
  • 创建订单。
  • 更新库存。
  • 扣款操作。

sql语句

代码语言:sql复制
START TRANSACTION;

-- 检查库存
SELECT stock FROM products WHERE id = ?;

-- 如果库存大于0,继续执行以下语句
UPDATE shopping_cart SET quantity = quantity   1 WHERE user_id = ? AND product_id = ?;

INSERT INTO orders (user_id, product_id, quantity, total_price) VALUES (?, ?, ?, ?);

UPDATE products SET stock = stock - 1 WHERE id = ?;

UPDATE users SET balance = balance - ? WHERE id = ?;

COMMIT;

假设我们有一个在线购物平台的数据库,其中包含以下表:

  • products:存储商品信息,包含id, stock等字段。
  • shopping_cart:存储用户的购物车信息,包含user_id, product_id, quantity等字段。
  • orders:存储订单信息,包含user_id, product_id, quantity, total_price等字段。
  • users:存储用户信息,包含id, balance等字段。

Java代码

代码语言:java复制
import java.sql.*;

public class ShoppingCartService {
    private static final String URL = "jdbc:mysql://localhost:3306/shopping_platform";
    private static final String USER = "root";
    private static final String PASSWORD = "password";

    public void purchaseProduct(int userId, int productId, int productQuantity, double total_price) {
        Connection conn = null;
        PreparedStatement checkStockStmt = null;
        PreparedStatement updateCartStmt = null;
        PreparedStatement createOrderStmt = null;
        PreparedStatement updateStockStmt = null;
        PreparedStatement updateUserBalanceStmt = null;

        try {
            conn = DriverManager.getConnection(URL, USER, PASSWORD);
            conn.setAutoCommit(false); // 开始事务

            // 检查库存
            checkStockStmt = conn.prepareStatement("SELECT stock FROM products WHERE id = ?");
            checkStockStmt.setInt(1, productId);
            ResultSet rs = checkStockStmt.executeQuery();
            if (!rs.next() || rs.getInt("stock") < 1) {
                throw new Exception("Product out of stock.");
            }

            // 更新购物车
            updateCartStmt = conn.prepareStatement("UPDATE shopping_cart SET quantity = quantity   1 WHERE user_id = ? AND product_id = ?");
            updateCartStmt.setInt(1, userId);
            updateCartStmt.setInt(2, productId);
            updateCartStmt.executeUpdate();

            // 创建订单
            createOrderStmt = conn.prepareStatement("INSERT INTO orders (user_id, product_id, quantity, total_price) VALUES (?, ?, ?, ?)");
            createOrderStmt.setInt(1, userId);
            createOrderStmt.setInt(2, productId);
            createOrderStmt.setInt(3, productQuantity);
            createOrderStmt.setDouble(4, total_price);
            createOrderStmt.executeUpdate();

            // 更新库存
            updateStockStmt = conn.prepareStatement("UPDATE products SET stock = stock - 1 WHERE id = ?");
            updateStockStmt.setInt(1, productId);
            updateStockStmt.executeUpdate();

            // 扣款操作
            updateUserBalanceStmt = conn.prepareStatement("UPDATE users SET balance = balance - ? WHERE id = ?");
            updateUserBalanceStmt.setDouble(1, total_price);
            updateUserBalanceStmt.setInt(2, userId);
            updateUserBalanceStmt.executeUpdate();

            conn.commit(); // 提交事务
        } catch (Exception e) {
            if (conn != null) {
                try {
                    conn.rollback(); // 回滚事务
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (checkStockStmt != null) checkStockStmt.close();
                if (updateCartStmt != null) updateCartStmt.close();
                if (createOrderStmt != null) createOrderStmt.close();
                if (updateStockStmt != null) updateStockStmt.close();
                if (updateUserBalanceStmt != null) updateUserBalanceStmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

0 人点赞