假设我有以下实体:
@Entity
public class Foo {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
@ManyToOne(fetch = LAZY)
private EntityA a;
@ManyToOne(fetch = LAZY)
private EntityB b;
.
.
.
@ManyToOne(fetch = LAZY)
private EntityX x;
}
所有关系都是延迟加载的,因为在大多数情况下,业务逻辑不需要它们。接下来,假设有一个端点,它按ID返回特定Foo实体的所有数据。有两个选项可以检索数据:
1.依赖于延迟加载,这意味着X数据库请求将针对X关系进行。考虑到请求是轻量级的,并且每个表只获取1行,这种方法似乎很好。此外,对于代码维护来说,它更令人愉快。
1.编写一个大的HQL查询,JOIN获取所有必要的关系。这种方法只执行一个数据库请求,比上面的选项快几毫秒,但是,hibernate生成一个非常大的SQL,在特定的边缘情况下可能会有性能问题,开发人员必须维护一个大的HQL查询。
在这种情况下有什么最佳实践吗?哪种方法更适合这种特定的场景?
3条答案
按热度按时间2admgd591#
但是,Hibernate生成一个非常大的SQL,在特定的边缘情况下可能会有性能问题
我不太明白。“可能”这个词似乎在这里起了很大的作用。你有任何实际的证据表明SQL Hibernate会导致糟糕的性能吗?
因为一般来说,加入多个
@ManyToOne
关联是数据库能够非常有效地完成的事情,并且不太可能导致问题。需要明确的是,“一个非常大的SQL”无论如何都不是性能差的指标。
因此,您的选择2是推荐。
现在,另一方面,如果你加入多个
@OneToMany
关联,问题就会出现,所以对于这种情况,可能需要考虑更奇特的解决方案,例如,使用FetchMode.SUBSELECT
。但这不是你在上面的代码中展示的情况。xj3cbfub2#
我建议分成两种方法:
5t7ly7z53#
Hibernate Criteria提供了另一个选项来实现这一点。您可以使用setFetchMode()在运行时指定关联获取语义。像这样:
使用这种方法,您可以在大多数用例中保留实体中的延迟加载设置。只有在需要使用引用加载胖对象的端点上-使用上面的代码。Hibernate将生成一个包含所有连接的查询。正是您在第2点中想要的。但没有硬编码和容易出错的查询字符串。