在我的Web应用程序中,我有一个与Child具有OneToMany关系的Object。 选择我的对象时,我执行以下查询:
from Object o
然后我应该为每个对象打印它有多少个孩子
// Foreach
object.children.size()
假设对象有很多孩子(假设30'000); 它是浪费资源调用size()还是ORM框架(在我的情况下是Hibernate)会在没有加载所有孩子的情况下处理它?</ p>
答案 0 :(得分:4)
使用JPA(标准):
Entity.getCollection().size()
会触发延迟加载以检索所有子集合 - 所以是的,它会相当慢,除非你需要对所有/大多数元素进行操作。注意:对于JPA的所有(理智)实现,这不会发出30,000个单独的查询 - 它将发出一个在结果集中返回30,000行的查询。 @OneToMany(fetch=FetchType.EAGER)
EntityManager.getQuery()/getTypedQuery()/getNamedQuery()
(甚至通过getNativeQUery()
的SQL)使用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
静态配置2级缓存:
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>
然后标记哪些实体应自动缓存在二级缓存中:
@Cacheable(true)
@Entity
public class Employee {
...
}
使用专有方法(例如Hibernate“Extra-Lazy”系列):
答案 1 :(得分:2)
在JPA实现中启用日志消息并查看实际发送到数据库的数据库查询始终是个好主意。在你的情况下,我会说ORM可能会延迟加载所有对象,因此效率非常低。
答案 2 :(得分:1)
Hibernate有一个称为“额外懒惰”集合的特殊功能,它将完全按照您的建议执行。这意味着如果你在其中一个超级惰性集合上调用size()
,如果集合已经初始化,它将返回内存中的子节点数,但如果集合没有,则会查询数据库count
尚未初始化。目的是避免在绝对必要时初始化非常大的集合。其他超级懒惰的例子包括处理Collection.contains
/ Map.containsKey
来电,Map.get
来电,List.get(int)
等来电。
要使用注释标记一个非常懒的集合,您可以说@org.hibernate.annotations.LazyCollection( EXTRA )