2016-08-23 60 views
0

我无法加载子类的多态父项。包含声明似乎没有区别。ActiveJDBC渴望加载多态父母

子类:

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

父类:

public class ParentRequest extends Model { 

} 

查询应该急切地回到孩子+家长:

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 ms。

任何洞察力或帮助非常感谢。

注:我知道孩子只有一个家长。在不久的将来它会有几个。

编辑: 由于某些原因,反转查询产生更快的结果。也就是说,如果我搜索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

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

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毫秒的速度相当快,而“瓶颈”在其他地方。

你需要做的就是加载一个更大的数据集。

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

摘要: 如果您使用include()方法,您将有更少的数据库调用,但将分配更多的RAM。由您决定是否对您的应用程序更快。

+0

感谢您的快速回复!成员children.cachedParents.size是我可以在调试器中看到的东西,所以我不能解释为什么它是我拥有它,而你不知道。无论出于何种原因,我发现如果我颠倒搜索,那是做一个连接两个表的查询,然后用一个包含(Child.class)的ParentRequest来获得更好的性能。询问我上面的方式花费大约25-35秒才能返回500点。询问我在这个评论中提到的方式,让我在12-15秒或更短的时间内得到500分。我会在下面发布我的psudocode。 –

+0

我很高兴看到框架按预期工作(我确信在100个案例中有99个是这样的)。我想知道我能做些什么不同。 –

+0

启用日志记录:http://javalite.io/logging并查看您的案例中生成了哪些查询。之后,您可以在数据库控制台中手动运行这些代码,运行解释并找出为什么有些更快,而其他更慢。 ActiveJDBC只是一个工具 - 它给你的选择:) – ipolevoy