ActiveJDBC 预加载多态 Parents

ActiveJDBC eager loading of Polymorphic Parents

我无法急切加载 child class 的多态 parent。 include 语句似乎没有什么区别。

Child Class:

@BelongsToPolymorphic(
    parents = {ParentRequest.class},
    typeLabels  = {"parent_request"})
public class Child extends Model {
}

Parent Class:

public class ParentRequest extends Model {

}

急切的查询 return child + parent:

List<Child> children = Child.where("... limit 500").include(ParentRequest.class);

children.size(); //this gives me 500
children.cachedParents.size(); //this gives me 0;

最终,我试图加快以下操作:

for (Child child : children) {
     ParentRequest pr = child.parent();
     // lots of pr.getString("parent_field");
     ...
 }

我已经对这些操作进行了测试,无论是否在 Child.where() 方法上使用 .include(ParentRequest.class) ,上述操作似乎都需要大约 67 毫秒。

非常感谢任何见解或帮助。

注意:我知道 Child 只有一个 parent。近期还会有好几个。

编辑: 由于某些原因,反转查询会产生更快的结果。也就是说,如果我搜索 ParentRequest 并包含 Child,而不是查找 Children 并包含 ParentRequest,操作会快得多。请注意,我专门做了一个 findBySql 以将 child table 加入我的结果中的 parent_request table。下面我留下了查询的细节。

List<ParentRequest> parents = ParentRequest.findBySQL("SELECT child.*, parent_requests.* " +
                "FROM child JOIN parent_requests ON child.parent_id=parent_requests.id WHERE " +
                "RAND()<=? AND (child.metersToA BETWEEN ? AND ?) " +
                        " AND (child.metersToB BETWEEN ? AND ?) limit ?",
                decimation_value,
                minDistanceToA, maxDistanceToA ,
                minDistanceToB, maxDistanceToB,
                MAX_POINTS).include(Child.class);

我写了一个简单的测试,启用了日志记录

Article article = Article.findById(1);
article.add(Comment.create("author", "tjefferson", "content", "comment 1"));
article.add(Comment.create("author", "tjefferson", "content", "comment 2"));
LazyList<Comment> comments = Comment.where("author = ?", "tjefferson").include(Article.class);

System.out.println(comments.size());// does loading of data, prints 2
Article parent1 = comments.get(0).parent(Article.class); // does not generate DB query
Article parent2 = comments.get(1).parent(Article.class); // does not generate DB query

assert (parent1 == parent2); // true

执行此代码会将以下内容记录到控制台:

SELECT * FROM comments WHERE author = ?", with parameters: <tjefferson>, took: 1 milliseconds
SELECT * FROM articles WHERE id IN (?)", with parameters: <1>, took: 1 milliseconds

如您所见,只有两次对数据库的查询。 此外,您提到的行:

children.cachedParents.size(); //this gives me 0;

不会编译,因为 LazyList 没有成员 cachedParents

如果在这种情况下遍历子项,并得到如下父项:

child.parent(Parent.class)

,不会有数据库查询到数据库,因为对象缓存在内存中。

该框架正在按预期工作。 在有和没有 include() 的情况下,您的时间相同的原因是数据集的大小。 67 毫秒非常快,"bottleneck" 在其他地方。

要查看差异,您需要做的是加载更大的数据集。

此外,请记住,加载的数据越多,分配的堆 space 就越多。最终 include() 方法解决了 N+1 问题 (http://javalite.io/lazy_and_eager) ,但这并不意味着你的应用程序会更快。您需要进行试验,并决定是否最好将它用于您的案例。

总结: 如果你使用 include() 方法,你对数据库的调用会更少,但会分配更多的 RAM。是否更快由您决定。