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

ActiveJDBC中含自动生成时间戳的复合主键父子表配置问题

解决方案:ActiveJDBC处理含自动时间戳的复合主键关联

可行性结论

完全可行,核心是正确配置复合主键注解,并处理数据库自动生成时间戳的同步问题。

修正后的Model配置

先修正Model的注解错误,添加复合主键声明:

ARecord(父表Model)

@Table("some_schema.a")
@CompositePK({"id", "insert_date"}) // 显式声明复合主键
public class ARecord extends Model {
}

BRecord(子表Model)

@Table("some_schema.b")
@CompositePK({"id", "insert_date"}) // 声明自身的复合主键
@BelongsToParents({
    @BelongsTo(foreignKeyName = "a_id", parent = ARecord.class),
    @BelongsTo(foreignKeyName = "a_insert_date", parent = ARecord.class)
}) // 关联父表的复合外键
public class BRecord extends Model {
}

正确的数据持久化流程

insert_date是数据库端通过默认值生成的,ActiveJDBC不会自动将该值同步到内存对象,因此必须手动刷新父对象获取真实值后,再关联子对象:

// 1. 创建并保存父对象
ARecord a = new ARecord();
// 若有其他业务字段,在此设置:a.set("xxx", value);
a.saveIt();
// 关键步骤:刷新对象,从数据库拉取自动生成的insert_date
a.refresh();

// 2. 创建子对象并关联父对象
BRecord b = new BRecord();
// 设置子对象自身业务字段:b.set("xxx", value);
// 手动填充复合外键的两个字段
b.set("a_id", a.getInteger("id"));
b.set("a_insert_date", a.getTimestamp("insert_date"));
// 保存子对象
b.saveIt();

// 也可以用ActiveJDBC关联方法(需确保父对象已刷新)
// a.add(b); // 此方法会自动保存子对象并填充外键

优化技巧:自动刷新父对象

如果不想每次保存后手动调用refresh(),可以重写父Model的saveIt()方法:

@Override
public ARecord saveIt() {
    super.saveIt();
    refresh();
    return this;
}

之后使用时只需:

ARecord a = new ARecord().saveIt(); // 自动完成刷新
BRecord b = new BRecord();
b.set("a_id", a.getInteger("id"));
b.set("a_insert_date", a.getTimestamp("insert_date"));
b.saveIt();

关键注意点

  • 必须添加@CompositePK注解:ActiveJDBC默认仅识别id为单主键,复合主键需显式声明,否则框架无法正确处理关联逻辑。
  • 数据库生成字段需手动刷新:对于数据库端生成的默认值(如CURRENT_TIMESTAMP),ActiveJDBC不会自动同步到内存对象,必须通过refresh()从数据库拉取最新数据。
  • 复合外键需完整填充:关联子对象时,必须确保两个外键字段(a_id和a_insert_date)都被正确设置,缺一不可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:40:21