在此场景中,利用 SQL 事务将数据插入到三个表中:Customer、Order 和 OrderItems。预期的行为是,如果事务中的任何查询失败,则应回滚整个事务,以确保数据一致性。但是,事务似乎没有按预期运行,因为当后续查询遇到错误并且无法将数据插入表时,它们不会回滚。
import { Request, Response } from 'express';
import { Order } from "../models/order.model";
import IResponse from "../interfaces/response.interface";
import { CustomerModel } from '../models/customer.model';
import db from '../database';
import { OrderItems } from '../models/orderitem.models';
import ProductModel from '../models/product.model';
class OrderController {
async createOrder(req: Request, res: Response): Promise<void> {
interface Product {
product_id: number;
name: string;
quantity: number;
price: number;
}
try {
const { products, name, email, phone, address } = req.body;
let totalPrice = 0;
// Calculate total price
products.forEach((product: Product) => {
const subtotal = product.quantity * product.price;
totalPrice += subtotal;
});
const result = await db.transaction(async (t) => {
// Create customer
const customer = await CustomerModel.create({
name: name,
email: email,
phone: phone,
address: address,
transaction: t // Assign transaction
});
const cust_id = customer.customer_id;
// Create order
const order = await Order.create({
customer_id: cust_id,
total_amount: totalPrice,
order_date: new Date(),
created_by: '1',
transaction: t // Assign transaction
});
const order_id = order.order_id;
// Create order items
const orderItemsPromises: Promise<void>[] = products.map((product: Product) => {
return OrderItems.create({
order_id: order_id,
product_id: product.product_id,
order_date: new Date(),
quantity: product.quantity,
price: product.price,
transaction: t // Assign transaction
});
});
// Wait for all order items to be created
await Promise.all(orderItemsPromises);
return order; // Return the order created within the transaction
});
res.status(201).json({ message: 'Order created successfully' });
} catch (error: any) {
// Send error response
console.error(error);
const response: IResponse = {
statusCode: 500,
status: 'error',
message: error.message,
data: '',
};
res.status(500).json(response);
}
}
}
在 sqquelize 文档和尝试的托管事务中,把事务涉及的所有查询都封装在事务块内。这可以确保如果任何查询失败,整个事务都会回滚。但它没有按预期工作?
const customer = await CustomerModel.create({
name: name,
email: email,
phone: phone,
address: address,
transaction: t // Incorrectly included in the data object
});
阅读“Sequelize Transactions”,事务对象应作为选项对象的一部分传递,而不是在正在创建或更新的数据对象内传递。
您需要每个 Sequelize 操作(在本例中为
create
)将事务 (t
) 从数据对象移动到选项对象(create
方法的第二个参数):
const customer = await CustomerModel.create({
name: name,
email: email,
phone: phone,
address: address,
}, { transaction: t }); // Correctly pass transaction here
订购:
const order = await Order.create({
customer_id: cust_id,
total_amount: totalPrice,
order_date: new Date(),
created_by: '1',
}, { transaction: t });
和订单项目:
const orderItemsPromises = products.map((product: Product) => {
return OrderItems.create({
order_id: order_id,
product_id: product.product_id,
quantity: product.quantity,
price: product.price,
}, { transaction: t });
});