java - 使用 JOIN FETCH 性能问题查询

标签 java hibernate

我无法解决 hibernate 查询性能问题。在下面的代码片段中,我需要选择至少具有一个映射和过滤映射的实体。为此,我使用 FETCH JOIN 仅加载过滤后的映射。 但在那种情况下,我遇到了查询性能问题。 Hibernate 说警告日志:

org.hibernate.hql.ast.QueryTranslatorImpl - firstResult/maxResults specified with collection fetch; applying in memory!

当我省略 FETCH JOIN 并只留下 JOIN 查询时,速度很快。但结果我将所有映射加载到实体,这对我来说是 Not Acceptable 状态。有没有办法提高查询性能?映射表中有很多行。

HQL 查询:

select distinct e from Entity 
   join fetch e.mappings as mapping 
where e.deleted = 0 and e.mappings is not empty 
   and e = mapping.e and mapping.approval in (:approvals)

实体:

@Entity
@Table(name="entity")
class Entity {

   ...

   @OneToMany(mappedBy="entity", cascade=CascadeType.REMOVE, fetch=FetchType.LAZY)
   @OrderBy("created")
   private List<Mapping> mappings = new ArrayList<Mapping>();

   ...
}

@Entity
@Table(name="mapping")
class Mapping {

public static enum MappingApproval {
    WAITING, // mapping is waiting for approval
    APPROVED, // mapping was approved
    DECLINED; // mapping was declined
}

...

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="entity_id", nullable=false)
    private Entity entity;

    @Enumerated(EnumType.STRING)
    @Column(name="approval", length=20)
    private MappingApproval approval;

...

}

谢谢

最佳答案

来自 JPA 规范

The effect of applying setMaxResults or setFirstResult to a query involving fetch joins over collections is undefined. (JPA "Enterprise JavaBeans 3.0, Final Release", Kapitel 3.6.1 Query Interface)

Hibernate 做了正确的事情,但是在内存中执行了一部分查询,这非常慢。在我的例子中,差异在 3-5 毫秒到 400-500 毫秒之间。

我的解决方案是在查询本身内实现分页。使用 JOIN FETCH 可以快速工作。

关于java - 使用 JOIN FETCH 性能问题查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4944985/

相关文章:

java - 这是什么 java.lang.NullPointerException?

java - Freemarker 迭代映射列表中的 HashMap

java - JLabel 未出现在 JFrame 上

java - @SQLResultSetMapping 未找到列问题

java - 如何使用 hibernate 更新没有主键的数据库记录

java - 从@OneToMany 关系中删除一个 child

java - 如何在jni接口(interface)中将值放入字节数组

java - 有没有办法打包jar依赖项以便在独立环境中运行java类

spring - 获取一系列 SQL 警告 : "relation <table> does not exist, skipping"

java - 为什么我需要在 Hibernate 中进行事务以进行只读操作?