Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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 休眠别名-仍然执行n+1选择是否正常?_Java_Hibernate - Fatal编程技术网

Java 休眠别名-仍然执行n+1选择是否正常?

Java 休眠别名-仍然执行n+1选择是否正常?,java,hibernate,Java,Hibernate,我有一个非常具体的两部分问题,我真的希望以前没有人问过: 首先是背景 我有一些Hibernate bean,它们之间有惰性关联,例如: @Entity public class SalesData { @ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(nullable = false) public Product getProduct() {

我有一个非常具体的两部分问题,我真的希望以前没有人问过:

首先是背景

我有一些Hibernate bean,它们之间有惰性关联,例如:

@Entity
public class SalesData {

   @ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
   @JoinColumn(nullable = false)
   public Product getProduct() {
     return product;
   }

}
然后是:

@Entity
public class Product {

  @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  public Set<SoundRecording> getSoundRecordings() {
    return soundRecordings;
  }

}
现在,如果我进行一个条件查询,将SalesData的别名添加到Product关系中,然后将Product的别名添加到SoundRecording中,如下所示:

Criteria criteria = session.createCriteria(SalesData.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("product", "p");
criteria.createAlias("p.soundRecordings", "s");
我可以在Hibernate的日志中看到,他生成SQL,例如:

select ... from SalesData this_ 
inner join Product p1_ on this_.product_id=p1_.id 
    inner join SoundRecording s5_ on p1_.id=s5_.product_id 
        where ...
当我调用criteria.list时,这正是我想要的。但是,如果我这样做:

salesDatas.getProduct().getSoundRecordings(0);
我可以在日志中看到,Hibernate进行了另一个特定的SQL select查询以检索此关联:

select ... from SoundRecording soundrecor0_ where soundrecor0_.product_id=?
我的问题是:


这正常吗?这里我的目标是用一个SQL查询一次性加载我特别需要的所有内容,这样我就可以避免这些n+1选择。我认为使用alias是实现这一点的一种方法,特别是因为我可以清楚地看到his在表之间生成一个内部联接。如果我使用explicitfetchmodejoin,那么hibernate不会发出所有额外的选择,它将满足于具有许多外部连接的初始选择。那么,为什么别名生成的联接不是如此呢?

别名或子标准用于创建联接。此连接可能有两个目标:

通过对连接的实体添加限制来限制返回值集 选择连接实体的字段 如果想要1而不想要2,则不需要获取,因此不应调用setFetchMode。如果您想要2,则需要获取


示例:您可能希望搜索当月有订单的所有产品,但对订单的字段一点也不感兴趣。在这种情况下,获取产品订单是不必要的,如果某些产品在一个月内有数百或数千个订单,那么获取成本将非常高。

同意,我明白你的意思,我没有理解,你是对的。但是,如果我有一个复杂的条件查询,其中我需要别名一个连接,以便稍后在查询中重用它,例如,一个子连接,但我还需要急切地从joinet实体/表中获取所有值。这样我就不得不使用alias,但如果我想的话,我就不能进行快速加载。在别名不起作用后添加setFetchModeJOIN,仍然会生成N+1选择…您完全可以在具有别名的关联上使用提取:c.createAliasproduct.orders,order;c、 setFetchModeproduct.orders,FetchMode.JOIN;嗯,是的,你至少对这个项目有95%的把握。我可以诚实地告诉你,只要做c.createAliasproduct.orders,order;c、 setFetchModeproduct.orders,FetchMode.JOIN;不起作用,我还是会得到额外的选择。但是,在进一步研究之后,我发现您可以这样做:criteria.createAliasassociationPath,alias,criteria.LEFT\u JOIN;条件.setFetchModeassociationPath,FetchMode.SELECT;现在它可以工作了,我有了别名连接和快速抓取,没有额外的选择。哇!谢谢你给我指明了正确的道路!
select ... from SoundRecording soundrecor0_ where soundrecor0_.product_id=?