简短的回答是:视情况而定 ...
这样的注释只声明你的实体如何连接以及它们如何相互依赖(与表格中的行数无关)......当使用它们时,JPA 提供程序允许您:
-
创建通过实体路径导航的 JPA 查询。
-
为您将实体加载到内存中,无需自己创建/执行其他查询,只需访问任何实体上的 getter 或 setter ...
可能会出现“性能问题”,具体取决于您的用例、您的数据有多大、您如何访问数据以及其他条件(顺便说一下,我之所以引用,是因为可能再多几秒钟就无法成为你的瓶颈)......让我举几个例子。
假设我们的实体是:Department 和 Employee...一个Department 可以有多个Employees(因此它会有一个注释为@OneToMany 的员工列表)...一个@ 987654331@ 只能在一个Department 中工作(因此它将有一个注释为@ManyToOne 的部门属性)...
您可能遇到的加载问题:
问题#1:您需要从数据库中加载一个Employee...默认情况下,@ManyToOne 有一个EAGER 获取计划,这意味着一旦您加载了一个@ 987654337@,JPA Provider 也会为您加载他关联的Department(为此,它将执行另一个查询)。这里的问题是您的用例可能不需要Department 信息,并且JPA 提供程序会无缘无故地访问数据库。 解决方案:将@ManyToOne标记为获取LAZY。
问题#2:您将@ManyToOne 标记为获取LAZY,但您有一个业务案例,您确实需要Employee 加上他的Department 信息......只想在一次访问数据库(仅一次查询)中完成此操作,并避免 JPA 提供程序在问题 #1 中所做的事情。 解决方案:您可以使用fetch 图表加载您的Employee 实体。
问题#3:您正在加载一组Employees,并且您需要访问他们的Department 信息...您加载这样的组,对于每个员工,您访问他的部门为:employees.stream().map(Employee::getDepartment) ... 你注意到 JPA 提供程序调用数据库 N 次来获取部门信息......这被称为:N+1 problem(你可以搜索它)......解决方案:使用获取图形或配置您的 JPA Provider 以使用 batch strategy 加载实体。
问题#4:您需要加载一个Department 并访问它的所有Employees ...您注意到通过执行:department.getEmployees(),需要一些时间来加载将所有数据放入内存。 解决方案:检查你的数据库模型,可能需要有一些索引。
问题#5:您需要加载一个Department 并访问它的所有Employees ...您有索引等等,但您确定这些表有数百万行...您不需要一次加载所有数据,因为它可能会产生OutOfMemoryProblems。 解决方案:您通过循环和使用批量策略加载Employees(请参阅MaxResults 和FirstResult)
如您所见,问题和解决方案与业务案例密切相关。
总结一下,
-
使用注释,并使用您计划在生产中遇到的数据样本进行一些测试,运行您的数字。根据经验,建立关系总是一个好主意fetch=LAZY。
-
如果您认为存在性能问题,请先启用 JPA 提供程序调试模式。它将向您显示正在执行的查询,并帮助您检测您面临的问题...
-
确定问题后,开始考虑您的业务案例提出解决方案。请记住,没有灵丹妙药或万能的解决方案,因此正确的解决方案将与您的用例相关联...