繁体   English   中英

用于检索复杂实体的高效JPQL查询

[英]Efficient JPQL query for retrieving complex entities

我是JPA / JPQL的新手,所以如果这个问题不清楚,请原谅。

我试图找到一个有效的JQPL查询,以获取复杂对象的所有记录。

(即由多个表表示,具有多个一对多关系 - 请参阅下面的简化示例):

class ComplexObject {
    private Set< SubOject1> so1 ...
    .....
    @OneToMany(fetch = FetchType.LAZY)
    public Set< SubOject1>...
}

class SubObject1 {
    private Set< SubOject2> so2 ...
    .....
    @OneToMany(fetch = FetchType.LAZY)
    public Set< SubOject2>...
}

我使用以下JPQL查询:

select distinct CO 
from ComplexObject CO 
left join fetch CO.so1 SO1 
left join fetch SO1.so2

查询在无状态会话上运行,以便获得DB中当前数据的事实上的快照,该快照与实体管理器分离(因此使用左连接提取)。

不幸的是,我遇到了两个问题:

  1. 由于复杂对象包含so1的多个实例,并且每个so1实例包含so2的多个实例,因此对SQL查询的基础转换会为所有表连接的每一行产生一个特定的选择查询 - 这是一个非常浪费的解决方案。 有没有办法减少内部选择查询的数量? (这似乎是可怕的N + 1查询问题)。

  2. JPQL查询在所有表连接的产品上为每个内部SQL查询返回一个ComplexObject实例 - 这意味着对ComplexObject实例的多个引用。 为什么会在'select distinct'查询中发生这种情况?

我使用的JPA框架是hibernate,而DB是HyperSQL。

(1)问题与使用p6spy日志框架有关,该框架打印出来自大型数据库表的所有结果。 日志记录格式导致错误的假设,即许多查询正在执行。

在尝试微调性能时,使用本机查询似乎没有比使用JPQL查询更好的性能。 使用本机查询还会导致对象类型的结果,这需要后期处理。

您可以使用“查看对象”仅接收所需的列:

StringBuilder sb = new StringBuilder();
sb.append(" SELECT new ").append(ObjectVO.class.getName()).append("(co.someInfo1, co.someInfo2, so1.someInfo )");
sb.append(" FROM ComplexObject co ");
sb.append(" JOIN co.subOject1s so1 ");
sb.append(" LEFT JOIN so1.so2 so2 ");
sb.append(" WHERE so1.id = :idSo1 AND so2 = :someThing");

Query q = em.createQuery(sb.toString());
q.setParameter("idSo1", idSo1);
q.setParameter("someThing", someThing);

List<ObjectVO> listResult = q.getResultList();

ObjectVO类:

public class ObjectVO {

    private String info1;
    private Long info2; 
    private String info3;

    public PedidoModel(String info1, Long info2, String info3){
        this.info1 = info1;
        this.info2 = info2;
        this.info3 = info3;
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM