如何在Adonis.js中实现多对多关系的软删除?
在Adonis.js中为多对多关系实现中间表软删除
1. 先给中间表建独立模型
别依赖Adonis自动生成的关联逻辑,给中间表(比如叫OrderItem)单独写个模型,把软删除字段加上并启用软删除:
// app/Models/OrderItem.js import { DateTime } from 'luxon' import { BaseModel, column, belongsTo } from '@ioc:Adonis/Lucid/Orm' import Order from './Order' import Item from './Item' export default class OrderItem extends BaseModel { @column({ isPrimary: true }) public id: number @column() public orderId: number @column() public itemId: number @column.dateTime({ autoCreate: true }) public createdAt: DateTime @column.dateTime({ autoCreate: true, autoUpdate: true }) public updatedAt: DateTime @column.dateTime() public deletedAt: DateTime | null // 开启软删除功能 public static softDelete = true @belongsTo(() => Order) public order: BelongsTo<typeof Order> @belongsTo(() => Item) public item: BelongsTo<typeof Item> }
2. 自定义多对多关联的查询规则
在Order和Item模型里,不用默认的@manyToMany装饰器直接关联,而是通过中间表模型手动加筛选条件:
订单模型关联商品
// app/Models/Order.js import { BaseModel, column, manyToMany } from '@ioc:Adonis/Lucid/Orm' import Item from './Item' import OrderItem from './OrderItem' export default class Order extends BaseModel { // 其他订单字段... // 获取订单里的有效商品(中间表未软删除的记录) public items() { return this.manyToMany(() => Item) .pivotModel(() => OrderItem) .wherePivot('deleted_at', null) } // 获取订单中已取消的商品(中间表软删除的记录) public cancelledItems() { return this.manyToMany(() => Item) .pivotModel(() => OrderItem) .wherePivot('deleted_at', '!=', null) } }
商品模型关联订单
// app/Models/Item.js import { BaseModel, column, manyToMany } from '@ioc:Adonis/Lucid/Orm' import Order from './Order' import OrderItem from './OrderItem' export default class Item extends BaseModel { // 其他商品字段... // 获取商品当前所属的有效订单(因为同一时间只能属于一个,加limit(1)) public activeOrder() { return this.manyToMany(() => Order) .pivotModel(() => OrderItem) .wherePivot('deleted_at', null) .limit(1) } // 获取商品曾被取消的订单记录 public cancelledOrders() { return this.manyToMany(() => Order) .pivotModel(() => OrderItem) .wherePivot('deleted_at', '!=', null) } }
3. 取消订单时的软删除操作
取消订单别删中间表记录,直接更新deleted_at字段就行:
// 订单控制器的取消方法示例 import Order from 'App/Models/Order' import OrderItem from 'App/Models/OrderItem' import { DateTime } from 'luxon' export default class OrdersController { public async cancel({ params }) { const order = await Order.findOrFail(params.id) // 把该订单下所有中间表记录标记为软删除 await OrderItem.query() .where('order_id', order.id) .update({ deletedAt: DateTime.local() }) return { message: '订单已取消,商品回归库存' } } }
4. 常用查询示例
- 拿某订单的有效商品:
const order = await Order.find(1) const activeItems = await order.related('items').query()
- 拿某商品当前的有效订单:
const item = await Item.find(1) const activeOrder = await item.related('activeOrder').query().first()
- 查看某订单取消过的商品记录:
const order = await Order.find(1) const cancelledItems = await order.related('cancelledItems').query()
这样既满足了“同一商品仅属一个有效订单”的要求,又能完整保留取消订单的商品记录,完全适配你的业务场景。
内容的提问来源于stack exchange,提问作者Milan Smolík
相关产品推荐
相关产品推荐

