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),虽能加载子记录,但会产生额外数据库调用,不符合预加载预期。
问题原因
- 未触发预加载的内存绑定:原代码未调用
load()方法,LazyList采用延迟加载模式,逐个加载Parent实例时,预加载的Child数据无法与对应Parent实例完成关联,导致getAll()返回空。 - 方法调用顺序错误:尝试添加
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
相关产品推荐
相关产品推荐

