
fastapi中执行异步数据库删除时,若仅调用session.execute()而未提交事务,会导致sql语句执行但数据未真正从数据库移除——这是初学者最易忽略的关键点。
fastapi中执行异步数据库删除时,若仅调用session.execute()而未提交事务,会导致sql语句执行但数据未真正从数据库移除——这是初学者最易忽略的关键点。
在使用SQLAlchemy 2.0+(配合async_session_maker)进行异步CRUD操作时,执行DML语句(如DELETE、INSERT、UPDATE)后必须显式调用session.commit(),否则更改仅停留在当前事务上下文中,随着会话结束而自动回滚,表现为“返回200 OK但数据未删除”。
你的原始代码中已正确构建了删除查询并执行:
delete_query = delete(Bookings).filter_by(room_id=room_id, user_id=user_id) await session.execute(delete_query) # ✅ 执行SQL,但未持久化
但缺少关键的提交步骤,因此数据库状态未变更。
✅ 正确写法如下(含错误处理与完整性优化):
@classmethod
async def remove(cls, user_id: int, room_id: int):
async with async_session_maker() as session:
# 可选:验证房间是否存在(根据业务需求)
room_check = select(Rooms).where(Rooms.id == room_id)
room = await session.scalar(room_check)
if not room:
raise HTTPException(status_code=404, detail="Room not found")
# 构建并执行删除语句
stmt = delete(Bookings).where(
Bookings.room_id == room_id,
Bookings.user_id == user_id
)
result = await session.execute(stmt)
# ⚠️ 关键:必须提交事务才能持久化删除
await session.commit()
# 可选:检查是否实际删除了记录
if result.rowcount == 0:
raise HTTPException(
status_code=404,
detail="No booking found for the given user and room"
)同时,确保路由层正确处理异常并返回语义化响应:
@router.delete("/{id}")
async def remove_booking(
id: int,
user: Users = Depends(get_current_user),
):
await BookingDAO.remove(user.id, id)
return {"status": "success", "message": "Booking deleted"}? 注意事项:
- session.commit() 是异步方法,务必使用 await;
- 若使用 session.rollback() 或发生未捕获异常,事务将自动回滚,无需手动处理;
- 避免在删除前冗余查询无关数据(如原代码中对 Rooms 的查询),除非业务逻辑强依赖该校验;
- 建议统一使用 where() 而非 filter_by(),因后者仅支持列名等于字面量,不支持跨模型关联或复杂表达式(如 Bookings.room_id == room_id 更清晰且兼容性更好)。
总结:异步删除 ≠ 自动提交。牢记「执行 + 提交」两步缺一不可,这是保障数据一致性的基石。










