Express JS PUT请求报错:重复Product Id问题求助
问题解决:Express+PostgreSQL购物车PUT请求报重复主键错误(23505)
问题描述
使用Express JS连接PostgreSQL开发电商商城,包含商品目录表和用户购物车表(user_product),购物车表设有product_quantity字段。需求为点击「加入购物车」按钮时:
- 商品未在购物车:通过POST请求新增条目
- 商品已在购物车:通过PUT请求更新数量
但点击同一商品第二次时,触发PUT请求却出现PostgreSQL重复主键错误(错误码23505),POST和DELETE功能正常。
报错信息
{ length: 209, severity: 'ERROR', code: '23505', detail: 'Key (product_id)=(4) already exists.', hint: undefined, position: undefined, internalPosition: undefined, internalQuery: undefined, where: undefined, schema: 'public', table: 'user_product', column: undefined, dataType: undefined, constraint: 'user_product_pkey', file: 'nbtinsert.c', line: '670', routine: '_bt_check_unique' }
问题分析
- 客户端重复判断逻辑失效:
checkIfRepeatedInCart函数中,用product.id与传入的product_id匹配,但购物车列表itemsAddedToCartList中存储的商品字段为product_id而非id,导致无法识别已存在的购物车商品,误触发POST请求而非PUT,引发重复主键冲突。 - 数量计算逻辑错误:当前代码用原商品的
product_quantity(库存数量)加1作为新数量,而非购物车中该商品的当前数量,会导致更新结果不准确。
解决方案
1. 修正客户端重复判断函数
将字段匹配逻辑从product.id改为product.product_id,确保能正确识别购物车中已存在的商品:
const checkIfRepeatedInCart = (productId) => { return itemsAddedToCartList.find((product) => product.product_id === productId); }
2. 修正PUT请求的数量计算逻辑
从购物车列表中获取目标商品的当前数量,再加1得到新数量,并更新本地购物车列表:
else { // 从本地购物车列表找到对应商品 const cartItem = itemsAddedToCartList.find(item => item.product_id === product.product_id); const newQuantity = cartItem.product_quantity + 1; fetch(`http://localhost:5000/cart-products/${product.product_id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ product_quantity: newQuantity }) }) .then((response) => response.json()) .then((data) => { console.log(data); // 更新本地购物车列表的数量 itemsAddedToCartList = itemsAddedToCartList.map(item => item.product_id === product.product_id ? {...item, product_quantity: newQuantity} : item ); }) .catch((error) => console.error(error)); }
3. 可选:服务端原子更新优化(避免并发问题)
为防止并发场景下的数量更新错误,可将服务端的UPDATE语句改为数据库原子递增,无需客户端计算新数量:
app.put('/cart-products/:product_id', async (req,res) => { try { const { product_id } = req.params; // 数据库内直接递增数量,返回更新后的数据 const updatedQuantity = await pool.query( "UPDATE user_product SET product_quantity = product_quantity + 1 WHERE product_id = $1 RETURNING *", [product_id] ); res.json(updatedQuantity.rows[0]); } catch (error) { console.log(error.message); res.status(500).json({error: error.message}); } })
对应客户端PUT请求可简化为:
fetch(`http://localhost:5000/cart-products/${product.product_id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' } })
验证步骤
- 首次点击商品,确认POST请求成功插入购物车数据
- 再次点击同一商品,确认触发PUT请求而非POST
- 检查数据库中该商品的
product_quantity是否正确递增
内容的提问来源于stack exchange,提问作者curiousRedReptile
相关产品推荐
相关产品推荐

