You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:05:07