在使用遗留的Criteria API时,如何阻止Hibernate将关联加入到SQL SELECT语句中?
在使用Hibernate的旧版Criteria API,对一个 many-to-one 关联进行过滤,但只检索基实体类型时,生成的SQL仍然会把该关联的所有列加入到SELECT中吗?如下示例所示?
Entities
class User
{
long id;
boolean active;
Address address;
}
class Address
{
long id;
String streetNum;
String street;
String country;
}
Criteria with Alias
Criteria criteria = session.createCriteria(User.class, "u");
criteria.createAlias("u.address", "a");
criteria.add(Restrictions.eq("a.streetNum", "15"));
final List<User> users = criteria.list();
SQL generated
SELECT
u.id,
u.active,
a.id,
a.streetNum,
a.street,
a.country
FROM
user AS u
JOIN address AS a ON u.addressID = a.id
WHERE
a.streetNum = 15
SQL assumed
SELECT
u.id,
u.active
FROM
user AS u
JOIN address AS a ON u.addressID = a.id
WHERE
a.streetNum = 15
Performance problems
这会导致生成的SQL包含所有被连接的别名表的所有列,在列数众多、需要对多处关联进行筛选并进行分页的场景下,性能将受到极大影响。
该查询并不需要检索关联的列。
NHibernate
在C#的 NHibernate中,似乎他们有 Projections.rootEntity()(我猜是为了这种情况),但在Java版 Hibernate 5.5.7中没有。
解决方案
这是 @ManyToOne与 @OneToOne关系的默认急加载(EAGER fetching)行为。Criteria API默认会遵循映射层级的抓取配置。但在需要时,是否可以通过诸如 SetFetchMode("Bids", FetchMode.Lazy) 之类的方法显式控制这一行为,以在需要时禁用急加载?
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。