简体   繁体   English

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

[英]Efficient JPQL query for retrieving complex entities

I'm quite the rookie with JPA/JPQL, so please excuse me if this question is not crystal clear. 我是JPA / JPQL的新手,所以如果这个问题不清楚,请原谅。

I am trying to find an efficient JQPL query in order to get all records of a complex object. 我试图找到一个有效的JQPL查询,以获取复杂对象的所有记录。

(ie. represented by multiple tables, with several one-to-many relationships - see simplified example below): (即由多个表表示,具有多个一对多关系 - 请参阅下面的简化示例):

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>...
}

I am using the following JPQL query : 我使用以下JPQL查询:

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

The query is run on a stateless session, in order to get a de facto snapshot of the current data in the DB, which is detached from the entity manager (hence the usage of left join fetch). 查询在无状态会话上运行,以便获得DB中当前数据的事实上的快照,该快照与实体管理器分离(因此使用左连接提取)。

Unfortunately, I've encountered 2 problems : 不幸的是,我遇到了两个问题:

  1. Since the complex object contains multiple instances of so1, and each so1 instance contains multiple instances of so2, the underlying translation to SQL queries generates a specific select query per row of the product of all the table joins - a very wasteful solution. 由于复杂对象包含so1的多个实例,并且每个so1实例包含so2的多个实例,因此对SQL查询的基础转换会为所有表连接的每一行产生一个特定的选择查询 - 这是一个非常浪费的解决方案。 Is there a way to reduce the number of internal select queries? 有没有办法减少内部选择查询的数量? (This seems like the dreaded N+1 queries problem). (这似乎是可怕的N + 1查询问题)。

  2. The JPQL query returns a ComplexObject instance per internal SQL query on the product of all the table joins - which means multiple references to the ComplexObject instances. JPQL查询在所有表连接的产品上为每个内部SQL查询返回一个ComplexObject实例 - 这意味着对ComplexObject实例的多个引用。 Why does this happen on a 'select distinct' query? 为什么会在'select distinct'查询中发生这种情况?

The JPA framework I am using is hibernate, and the DB is HyperSQL. 我使用的JPA框架是hibernate,而DB是HyperSQL。

The (1) issue turned out to be related to using the p6spy logging framework, which printed out all the results from a large DB table. (1)问题与使用p6spy日志框架有关,该框架打印出来自大型数据库表的所有结果。 The logging format led to an incorrect assumption that many queries where being executed. 日志记录格式导致错误的假设,即许多查询正在执行。

While trying to fine tune performance, using native queries did not appear to have better performance then using JPQL queries. 在尝试微调性能时,使用本机查询似乎没有比使用JPQL查询更好的性能。 Using a Native Query also resulted in Object typed results, which required post processing. 使用本机查询还会导致对象类型的结果,这需要后期处理。

You can use View Objects to receive only the columns what you want: 您可以使用“查看对象”仅接收所需的列:

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();

The ObjectVO class: 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