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

Kotlin Exposed:如何用DAO及onUpdate级联自动创建子表记录

解答

不能通过onUpdate级联函数实现这个需求——onUpdate级联是用于父表记录更新时同步处理子表的逻辑,完全不涉及父表插入新记录的场景。不过可以通过Kotlin Exposed的DAO机制实现自动创建子表记录的需求,下面提供两种实用方案:

方案一:利用DAO的afterInsert钩子

在父表的DAO类中重写afterInsert方法,插入父记录后自动触发子记录的创建逻辑。

示例代码:

// 定义表结构
object ParentTable : IntIdTable() {
    val name = varchar("name", 50)
}

object ChildTable : IntIdTable() {
    val colA = reference("col_a", ParentTable).uniqueIndex() // 关联父表ID,唯一约束保证一一对应
    val colB = varchar("col_b", 50).default("默认值") // 设置默认值
}

// DAO实体类
class ParentEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<ParentEntity>(ParentTable)

    var name by ParentTable.name
    val child by ChildEntity referencedOn ChildTable.colA

    override fun afterInsert() {
        super.afterInsert()
        // 父记录插入完成后,自动创建对应子记录
        ChildEntity.new {
            colA = this@ParentEntity
            // colB会自动使用默认值,无需手动赋值
        }
    }
}

class ChildEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<ChildEntity>(ChildTable)

    var colA by ParentEntity referencedOn ChildTable.colA
    var colB by ChildTable.colB
}

使用方式:

transaction {
    ParentEntity.new {
        name = "父记录1"
    }
    // 此时ChildTable会自动生成一条对应记录:colA为该父记录ID,colB为预设默认值
}

方案二:事务内手动关联插入

如果不想依赖DAO的钩子方法,也可以在同一个事务中先插入父记录,紧接着创建子记录,保证操作的原子性。

示例代码:

transaction {
    val parent = ParentEntity.new {
        name = "父记录2"
    }
    // 手动创建对应子记录
    ChildEntity.new {
        colA = parent
        // colB自动使用默认值
    }
}

补充说明

  • 若要完全通过数据库层面触发逻辑,可以创建数据库触发器,但这不属于Exposed DAO的功能范畴。
  • 无论用哪种方案,都要将操作放在同一个transaction中,确保父、子记录的创建要么同时成功,要么同时回滚,避免数据不一致。

内容的提问来源于stack exchange,提问作者mars8

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 05:28:18