在我的web应用程序中,我有一个与Child具有OneToMany关系的对象。 当选择我的对象我执行以下查询:jpa儿童体型表现
from Object o
,然后我应打印的每个对象有多少孩子有
// Foreach
object.children.size()
假设对象有很多孩子(让我们说30'000); 是否浪费资源调用size()或者ORM框架(在我的情况下是Hibernate)会在不加载所有子项的情况下处理这个问题?
在我的web应用程序中,我有一个与Child具有OneToMany关系的对象。 当选择我的对象我执行以下查询:jpa儿童体型表现
from Object o
,然后我应打印的每个对象有多少孩子有
// Foreach
object.children.size()
假设对象有很多孩子(让我们说30'000); 是否浪费资源调用size()或者ORM框架(在我的情况下是Hibernate)会在不加载所有子项的情况下处理这个问题?
使用JPA(标准):
Entity.getCollection().size()
会触发延迟加载来检索所有的子集合 - 所以是的,它会相当缓慢,除非您需要对所有/大多数元素进行操作。注意:对于JPA的所有(理性)实现,这不会发出30,000个单独的查询 - 它将发出一个查询,返回结果集中的30,000行。@OneToMany(fetch=FetchType.EAGER)
getNativeQUery()
甚至SQL)通过EntityManager.getQuery()/getTypedQuery()/getNamedQuery()
使用JPQL。这是非常简单,具有高性能:int empSize = em.createQuery("SELECT SIZE(d.employees) FROM Department d") .getSingleResult();
OR ALTERNATIVELY
// Pre-compiled query placed against entity class for highest performance
@NamedQueries({
@NamedQuery(name="Department.EmployeeSize",
query="SELECT SIZE(d.employees) FROM Department"),
... // other named queries
})
@Entity
public class Department {
...
}
// Then to use the query:
int empSize = em.createNamedQuery("Department.EmployeeSize", Integer.class)
.getSingleResult();
您可以启用2级缓存。JPA Caching Summary
静态配置二级缓存:
Map propertiesMap = new HashMap(); // Valid values are ALL, NONE, ENABLE_SELECTIVE, DISABLE_SELECTIVE propertiesMap.add("javax.persistence.sharedCache.mode", "ENABLE_SELECTIVE"); EntityManagerFactory = Persistence.createEntityManagerFactory("myPUName", propertiesMap);
ALTERNATIVELY use persistence.xml:
<persistence-unit name="EmployeeService">
...
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
</persistence-unit>
然后标记哪些实体应在2级缓存自动缓存:
@Cacheable(true)
@Entity
public class Employee {
...
}
使用专有方法的一部分(例如休眠 “超懒” 的集合):
在您的JPA实现中启用日志消息并查看真正发送到数据库的数据库查询是个好主意。在你的情况下,我会说ORM可能会懒惰地加载所有对象,所以它会非常低效。
Hibernate有一个特殊的功能,称为“额外懒惰”的集合,将完全按照你刚才的建议。这意味着如果您在其中一个超懒集合上调用size()
,它将返回内存中的子数,如果该集合已经初始化的话,但是如果该集合尚未初始化,将会查询数据库count
。目的是避免初始化非常大的集合,直到绝对必要。其他例外的事情包括处理Collection.contains
/Map.containsKey
调用,Map.get
调用,List.get(int)
等调用。
为了纪念集合作为额外慵懒的注解,你会说@org.hibernate.annotations.LazyCollection(EXTRA)
那么,如果我想让每个对象都有多少个孩子,那么你的解决方案是什么? – ianaz
@ianaz做什么你会用普通的SQL做什么。例如,你可以编写一个查询,返回对象与计数,例如''来自Object o,(从child where parent.id = o.id)选择count(*)。“)。它仍然效率低下,但比指望Java方面更好。或者,您可以将查询拆分为两个查询,一个从Object o读取所有对象'',另一个按父级对所有孩子进行分组并返回计数,例如,按父级从子组中选择count(*)。 id“'并处理它。 –
编辑:最后一个查询应该是'“选择parent.id,通过parent.id从子组中计数(*)” –