Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用于检索复杂实体的高效JPQL查询_Java_Sql_Hibernate_Jpa_Jpql - Fatal编程技术网

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

Java 用于检索复杂实体的高效JPQL查询,java,sql,hibernate,jpa,jpql,Java,Sql,Hibernate,Jpa,Jpql,我是JPA/JPQL的新手,如果这个问题不太清楚,请原谅 我试图找到一个有效的JQPL查询,以便获得复杂对象的所有记录 即,由多个表表示,具有多个一对多关系-参见下面的简化示例: class ComplexObject { private Set< SubOject1> so1 ... ..... @OneToMany(fetch = FetchType.LAZY) public Set< SubOject1>... } class Su

我是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>...
}
查询在无状态会话上运行,以获取数据库中当前数据的实际快照,该快照与实体管理器分离,因此使用左连接获取

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

由于复杂对象包含多个so1实例,并且每个so1实例都包含多个so2实例,因此对SQL查询的底层转换会在所有表联接的乘积的每行生成一个特定的select查询,这是一个非常浪费的解决方案。有没有办法减少内部select查询的数量?这似乎是可怕的N+1查询问题

JPQL查询在所有表联接的乘积上的每个内部SQL查询返回一个ComplexObject实例,这意味着对ComplexObject实例的多个引用。为什么在“select distinct”查询中会发生这种情况

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

第一个问题与使用p6spy日志框架有关,该框架打印了一个大型DB表中的所有结果。日志记录格式导致错误的假设,即许多查询在哪里执行

在尝试微调性能时,使用本机查询似乎没有比使用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();

最有效的查询是类型化本机查询。如果您无法使用Hibernate或其他ORM开销,请不要使用条件或JPQL查询。@Baldurian:使用JPQL在一个事务中获取大部分数据库数据的一般概念有问题吗?在这种情况下,应该使用本机查询类型化本机查询如何比条件或JPQL查询更有效?命名查询的大多数处理都可以提前完成,并且无论是本地查询还是JPQL查询,都可以同样高效或低效,具体取决于查询本身。本机查询允许自定义,但大多数JPA提供程序都提供了一系列选项,如果您了解自己正在做什么,这些选项可以提高性能。@RannLifshitz一般来说,但是如果你不能忍受几个Hibernate愚蠢的查询,而且它们经常发生,你应该切换到本机查询。添加Hibernate标记作为第2部分中的行为是JPA提供者特有的。JPA不支持嵌套抓取,其他提供程序处理过滤掉连接多个关系可能导致的重复项。
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();
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;
    }

}