All*_*rry 5 java spring entity jpa entitygraph
我有两个处于一对一关系的实体(可以是多对一的关系,但对于这种情况我认为这并不重要),如下所示:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
//...
}
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String subject;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User otherUser;
//...
}
The repository looks like this
@EntityGraph(attributePaths = {"otherUser"})
Iterable<Post> findAll(Predicate predicate);
Run Code Online (Sandbox Code Playgroud)
因此,我重写了findAll它们默认提供的方法,因为我仍然想使用谓词,并且仍然想将查询连接到另一个表。这几乎可以完美地工作。创建的查询如下所示
select
post0_.id as id1_4_0_,
user0_.id as id1_0_1_,
post0_.subject as subject2_4_0_,
user0_.name as name2_0_1_,
user0_.email as email3_0_1_
from
Post post0_
left outer join User user0_ on post0_.id = user0_.id
where
***contents of Predicate****
Run Code Online (Sandbox Code Playgroud)
现在的问题是,如果用户从该查询返回基本上为 null(用户的所有属性都为 null,这意味着不存在与条件匹配的属性),那么 Spring 会直接向 User 表创建额外的选择查询来查找该用户。例如,假设有一篇 id=4 的帖子。如果没有 id = 4 的用户,那么 Spring 将创建并运行一个正常的查询,如下所示:
select
user0_.id as id1_0_1_,
user0_.name as name2_0_1_,
user0_.email as email3_0_1_
from
User user0_
left outer join User user0_ on post0_.id = user0_.id
where
user0_id = 4
Run Code Online (Sandbox Code Playgroud)
如果数据集很大并且包含大量不适合原始连接查询的记录,那么将创建并执行太多附加查询,这就是一个问题。如果它不符合连接标准,那么我希望忽略该实体记录。使用该示例,我希望忽略任何 id 与帖子 id 不匹配的用户,而不是另一个 select 语句。
有没有办法阻止创建这些额外的选择查询?
假设您通过日志语句使用 Hibernate,我相信您遇到了 n+1 sql 加载情况,并且需要添加不同/附加 FETCH 指令以使关联otherUser快速获取,因此不需要后续 select 语句。
我能找到的关于该主题的最权威的文档在这里:https ://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#fetching
我建议您首先将其更改FetchType.LAZY为FetchType.EAGER. FetchType.EAGER如果在成员变量上放置 JPA 注释otherUser不能解决您的问题,请考虑利用@Fetch(FetchMode.JOIN)它来进一步加强它。
另外,为了完整起见,如果您选择使用基于查询的方法来检索(即 JPQL),那么您可以在 JPQL 中包含 FETCH 指令,以根据需要实现效果。
| 归档时间: |
|
| 查看次数: |
1283 次 |
| 最近记录: |