jpa儿童尺寸表现

时间:2012-10-31 11:27:08

标签: hibernate jpa

在我的Web应用程序中,我有一个与Child具有OneToMany关系的Object。 选择我的对象时,我执行以下查询:

from Object o

然后我应该为每个对象打印它有多少个孩子

// Foreach
object.children.size()

假设对象有很多孩子(假设30'000); 它是浪费资源调用size()还是ORM框架(在我的情况下是Hibernate)会在没有加载所有孩子的情况下处理它?<​​/ p>

3 个答案:

答案 0 :(得分:4)

使用JPA(标准):

  • 默认情况下,@OneToMany关系是延迟加载的(即fetch = FetchType.LAZY的默认值)。但是调用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();    
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”系列):

  • 与简单发布JPQL / SQL查询相同的性能
  • 保存几行代码(@ org.hibernate.annotations.LazyCollection(EXTRA)注释v @NamedQuery注释和执行)
  • 不标准 - 受过JPA培训的开发人员不会知道它
  • 不可移植 - 只能与该供应商一起使用。标准JPA存在行业趋势,远离专有功能。许多不同的JPA实现都在那里。

答案 1 :(得分:2)

在JPA实现中启用日志消息并查看实际发送到数据库的数据库查询始终是个好主意。在你的情况下,我会说ORM可能会延迟加载所有对象,因此效率非常低。

答案 2 :(得分:1)

Hibernate有一个称为“额外懒惰”集合的特殊功能,它将完全按照您的建议执行。这意味着如果你在其中一个超级惰性集合上调用size(),如果集合已经初始化,它将返回内存中的子节点数,但如果集合没有,则会查询数据库count尚未初始化。目的是避免在绝对必要时初始化非常大的集合。其他超级懒惰的例子包括处理Collection.contains / Map.containsKey来电,Map.get来电,List.get(int)等来电。

要使用注释标记一个非常懒的集合,您可以说@org.hibernate.annotations.LazyCollection( EXTRA )