EntityManager.getResultList()上的性能降低

时间:2016-01-27 06:08:35

标签: java spring hibernate jpa entitymanager

我们在Web应用程序中使用Hibernate + Spring启动,我们在EntityManager中遇到性能问题以执行选择查询。该查询应返回20行并执行<在DBArtisan 1秒。但是,在代码中执行相同的查询9秒:

CriteriaQuery<Long> totalCriteriaQuery = criteriaBuilder.createQuery(Long.class);
        Root<M> totalRoot = totalCriteriaQuery.from(modelClass);
        totalCriteriaQuery.select(criteriaBuilder.count(totalRoot));
        if (searchCriteria != null) {
            totalCriteriaQuery.where(whereBuilder.build(searchCriteria, criteriaBuilder, totalRoot));
        }
        TypedQuery<Long> totalQuery = em.createQuery(totalCriteriaQuery);
        contentQuery.setFirstResult(pageRequest.getOffset());
        contentQuery.setMaxResults(pageRequest.getPageSize());
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<M> resultList = contentQuery.getResultList();
        stopWatch.stop();
        System.out.println("Nano seconds: "+ stopWatch.getNanoTime());

我正在寻找使用EM的原因或有关性能的任何建议。

3 个答案:

答案 0 :(得分:0)

如果您遇到性能不佳,则应尝试分析代码以查看性能问题的确切位置。我建议使用JProfiler来实现这个目的,它提供了非常清晰的结果,甚至报告了调用者函数。

您是否尝试过缓存查询,在使用Hibernate + Spring配置时它也可能有所帮助。如果您想提高效果JPA Performance Tuning,我建议您查看此页面。

P.S。根据我自己的经验,如果性能是您的第一选择,请尝试使用普通JDBC而不是EM。

答案 1 :(得分:0)

在幕后,Criteria API使用OFFSET和LIMIT进行分页,但don't scale用于大偏移值。

因此,随着页面的进一步发展,查询将变得越慢,但这是关系数据库的缺点。

您可以先使用key-set pagination并获取ID,然后使用这些来获取实体。

答案 2 :(得分:0)

事实证明我的实体有一个带有另一个表的连接列,hibernate生成的实际查询包含多个子查询。我为该列添加了以下注释,一旦我更改为LAZY,它会按预期加速,但不确定更改FetchType的含义。

 @ElementCollection(fetch = FetchType.EAGER)