ActiveJDBC渴望加载多态父母

时间:2016-08-23 03:45:54

标签: java polymorphic-associations activejdbc eager

我无法急切地加载子类的多态父级。包含声明似乎没有区别。

儿童班:

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

父类:

public class ParentRequest extends Model {

}

查询应该急切地返回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只有一个父母。在不久的将来它会有几个。

修改        由于某些原因,反转查询产生了更快的结果。也就是说,如果我搜索ParentRequest并包含Child,而不是寻找Children并包括ParentRequest,那么操作要快得多。请注意,我特意做了一个findBySql,将子表连接到我的结果中的parent_request表。下面我将在查询的具体内容中留下。

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);

1 个答案:

答案 0 :(得分:1)

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

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毫秒是相当快的,&#34;瓶颈&#34;在哪里。

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

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

要点: 如果使用include()方法,则对数据库的调用次数会减少,但会分配更多RAM。您可以自行决定是否更快地使用您的应用。