首先,我将解释我如何理解和使用@BatchSize
:
@BatchSize
用于批量加载对象关系,对数据库的SQL请求较少。这对 LAZY @OneToMany
关系特别有用。
然而,它甚至对 LAZY @OneToOne
关系和@ManyToOne
有用:如果从数据库加载实体列表并要求加载延迟{ {1}}实体,它将按批量加载实体,即使我只是使用加载列表的第一个实体的关系的测试。
注意是否有人想要测试:这只显示实体是否尚未加载:例如,如果你有一个带有管理员的用户列表并列出所有用户,当你将访问管理员时,不会触发任何请求因为它已经装好了。
我在该方法上看到的唯一缺点是,如果从数据库加载项目列表但仅使用其中的一部分。这是一个后过滤操作。
所以让我们谈谈要点。
让我们假设我做的一切都好,从不做类似后期过滤的操作,即使它让我做本机SQL查询或使用DTO对象进行多选标准查询等等。
@*ToOne
每个懒惰的关系? @BatchSize
寻找足够的价值,或者我认为"越大越好" ?这意味着"" IN"中的数字是否有限制? SQL运算符可以让我的请求足够慢,不再值得了吗?我使用Postgres,但如果你有其他SGBD的答案,我也感兴趣。 @BatchSize
并不会产生大量结果。我仍然需要注释每一个懒惰的关系,我是否想念它或者它没用?编辑:我的3点是我得到了不同的行为。
让我说我正在加载一个类的实体列表" A"与B的LAZY OneToMany关系。现在我要打印B的所有creationDate。所以我做了一个经典的2 for循环。
我现在用BatchSize注释了B:
PS:我没有考虑任何可能通过fetch select / subselect触发加载B字段的B相关查询。
编辑2:我刚刚发现这篇文章Why would I not use @BatchSize on every lazy loaded relationship?,但在我提出问题之前,我用Google搜索并搜索了SO,猜猜我没有使用正确的词......
但是我添加了一些可能会导致不同答案的不同之处:当我想知道在每个关系中使用BatchSize时,选择我是否想要一个急切的加载,然后加入/ select fetch或者我想要延迟加载。
答案 0 :(得分:5)
@BatchSize
旨在与懒惰关联一起使用。@BatchSize
表示实体的指定批量大小将应用于与该实体的所有@*ToOne
惰性关联。请参阅documentation中Person
实体的示例。您提供的关联问题/答案更关注优化和延迟加载的需求。它们当然也适用于此,但它们与批量加载无关,这只是可能的方法之一。
另一个重要的事情涉及链接答案中提到的热切加载,这表明如果始终使用属性,那么通过使用预先加载可以获得更好的性能。对于集合而言,这通常是不真实,在许多情况下,对于一个协会也是如此。
例如,假设您使用bs
时使用了cs
和A
始终的实体。
public class A {
@OneToMany
private Collection<B> bs;
@OneToMany
private Collection<C> cs;
}
如果你没有在单个查询中加入,那么急切地加载bs
和cs
显然会遇到N + 1选择问题。但是如果你在一个查询中加入它们,例如:
select a from A
left join fetch a.bs
left join fetch a.cs
然后在bs
和cs
之间创建完整笛卡尔积,并在每个count(a.bs) x count(a.cs)
的结果集中返回a
行,逐一阅读并汇总到A
的实体及其bs
和cs
的集合中。
在这种情况下,批量提取会非常理想,因为您首先会先阅读A
,然后是bs
,然后是cs
,这会导致更多查询,但总量会少得多从数据库传输的数据。此外,单独的查询比具有连接的大查询简单得多,并且数据库更容易执行和优化。