我有一个非常具体的2部分问题,我真的希望以前没有被问过:)
首先是上下文
我有一些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;
}
}
最后:
@Entity public class SoundRecording {
}
现在,如果我创建一个Criteria查询,我在其中为SalesData to Product关系添加别名,然后为Product to 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选择。我认为使用别名是一种方法,特别是因为我可以清楚地看到他在表之间生成内部联接。如果我使用explictit fetchMode(Join),那么hibernate将不会发出所有额外的选择,它将满足初始选择与许多(outter)连接。那么为什么对别名生成的连接不一样呢?
答案 0 :(得分:2)
别名或子标准用于创建连接。此联接可能有两个目标:
如果你想要1并且不想要2,则不需要提取,因此你不应该调用setFetchMode()
)。如果你想要2,那么就需要提取。
示例:您可能希望搜索当前月份中订单的所有产品,但不会对订单字段中的所有产品感兴趣。在这种情况下,不需要获取产品订单,如果某些产品在一个月内有数百或数千个订单,则会非常昂贵。