我有一个项目清单和一个客户名单。一个项目可以是为一个客户,每个客户可以有许多项目。因此,这是一个简单的1:n关系,其中项目是拥有的一方。
简化为本质
@Entity
public class Project {
@Id
long id;
@ManyToOne(optional = true)
@JoinColumn(name = "customer", nullable = true, updatable = true)
Customer customer;
}
@Entity
public class Customer {
@Id
long id;
}
当我加载项目列表时,我希望同时高效地检索客户。事实并非如此。对于项目只有一个查询,然后针对遇到的每个不同的客户发出单独的查询。
因此,假设我有100个项目分配给50个不同的客户。这将导致对项目的一个查询和对客户的50个查询。
这很快就会增加,对于大型项目/客户列表,我们的应用程序变得相当缓慢。这也只是一个例子。我们所有有关系的实体都会受到这种行为的影响。
我已经像建议的那样在@Fetch(FetchMode.JOIN)
字段上尝试了here,但是它什么也不做,根据Hibernate,FetchMode.SUBQUERY
是不适用的:
org.hibernate.AnnotationException:在ToOne关联中不允许使用FetchMode.SUBSELECT
我怎样才能解决这个问题?
发布于 2020-11-10 17:07:05
如果使用Spring Data JPA
实现存储库,则可以在JPA
实体中指定延迟抓取:
@Entity
public class Project {
@Id
long id;
@ManyToOne(fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "customer", nullable = true, updatable = true)
Customer customer;
}
@Entity
public class Customer {
@Id
long id;
...
}
并将@EntityGraph
添加到Spring Data JPA
-based存储库中:
@Repository
public interface ProjectDao extends JpaRepository<Project, Long> {
@EntityGraph(
type = EntityGraphType.FETCH,
attributePaths = {
"customer"
}
)
Optional<Project> findById(Long id);
...
}
我在https://tech.asimio.net/2020/11/06/Preventing-N-plus-1-select-problem-using-Spring-Data-JPA-EntityGraph.html的博客文章帮助您使用Spring Data JPA
和@EntityGraph
防止N+1选择问题。
发布于 2016-04-12 11:57:49
是的,这是n+1选择问题的一个活生生的例子.
在大多数情况下,我使用的方法是使关联变懒并定义一个batch size。
或者,您可以使用JPQL查询和[left] join fetch
直接从查询结果集初始化关联:
select p from Project p left join fetch p.customer
发布于 2019-04-30 17:48:45
是的,正如@dragan-bozanovic所说,这是n+1选择问题的一个活生生的例子。
在Spring-Boot2.1.3中,可以使用@Fetch(FetchMode.JOIN)
来解决这个问题:
@ManyToOne(optional = true)
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "customer", nullable = true, updatable = true)
Customer customer;
警告:如果关系可能无效,例如,当用@NotFound(action = NotFoundAction.IGNORE)
标记时,每个无效关系都将触发另一个SELECT
查询。
https://stackoverflow.com/questions/36569318
复制相似问题