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

ActiveJDBC中使用getAll(...)无法预加载子记录问题排查

ActiveJDBC子记录预加载问题排查与解决

问题描述

尝试通过@HasMany关联配合include()方法预加载Child记录,相关代码与异常现象如下:

表结构

Parent(id, name);
Child(id, name, parent_id);

Parent实体类

@HasMany(foreignKeyName = "parent_id", child = Child.class)
public class Parent extends Model {
}

Child实体类

public class Child extends Model {
}

测试代码

LazyList<Parent> parents = Parent.find("id in (115, 78)").include(Child.class);
for (Parent parent : parents) {
    int id = parent.getInteger("id");
    String name = parent.getString("name");
    System.out.println("ID:" + id);
    System.out.println("Name:" + id); // 注:此处存在笔误,应输出name而非id

    LazyList<Child> children = parent.getAll(Child.class);
    System.out.println("children: " + children.size());
}

异常现象

日志显示已执行Parent和Child的查询语句,但getAll(Child.class)返回子记录数为0(实际ID115有2条、ID78有3条)。若调整为Parent.find("id in (115, 78)").load().include(Child.class),虽能加载子记录,但会产生额外数据库调用,不符合预加载预期。

问题原因

  1. 未触发预加载的内存绑定:原代码未调用load()方法,LazyList采用延迟加载模式,逐个加载Parent实例时,预加载的Child数据无法与对应Parent实例完成关联,导致getAll()返回空。
  2. 方法调用顺序错误:尝试添加load()时顺序颠倒(load().include()),导致先加载所有Parent到内存,再为每个Parent单独查询Child,触发N+1查询,产生额外数据库调用。

解决方案

ActiveJDBC支持子记录预加载,关键是保证include()在load()之前调用,这样框架会先执行Parent查询,再根据Parent的ID批量查询Child,最后将Child数据关联到对应Parent实例,仅产生两次数据库调用。

正确代码如下:

LazyList<Parent> parents = Parent.find("id in (115, 78)").include(Child.class).load();
for (Parent parent : parents) {
    int id = parent.getInteger("id");
    String name = parent.getString("name");
    System.out.println("ID:" + id);
    System.out.println("Name:" + name);

    LazyList<Child> children = parent.getAll(Child.class);
    System.out.println("children: " + children.size()); // 直接从内存获取,无额外查询
}

同时修正测试代码中的笔误:将System.out.println("Name:" + id);改为System.out.println("Name:" + name);。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:17:41