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
相关产品推荐
相关产品推荐

