java - 即使使用 @Fetch(FetchMode.JOIN),JPA + Hibernate 也会出现太多查询问题
问题描述
我正在使用 Spring Boot 开发 REST 应用程序,并且正在尝试优化查询的性能。我目前正在使用findAll
导致性能问题的存储库。代码如下:
个人实体
@Entity
@Table(name = "cd_person")
@Data
@NoArgsConstructor
public class Person {
....
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "password_id")
@Fetch(FetchMode.JOIN)
private Password password;
....
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinTable(name = "cd_person_role",
joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
@Fetch(FetchMode.JOIN)
private Set<Role> roles = new HashSet<>();
}
密码实体
@Entity
@Table(name = "cd_password")
@Data
@NoArgsConstructor
public class Password {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Long id;
@Column(name = "password_hash", nullable = false)
private String passwordHash;
.......
}
角色实体
@Entity
@Table(name = "cd_role")
@Data
@NoArgsConstructor
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "role_type")
@Enumerated(EnumType.STRING)
private RoleType roleType;
....
}
个人资料库
public interface PersonRepository extends CrudRepository<Person, Long> {
Optional<Person> findByEmail(String email);
}
当我这样做时personRepository.findAll()
,会为 person 表中的每一行触发选择查询,以在我访问该人时获取密码和角色。我知道我可以在存储库中使用@Query
注释JOIN FETCH
来使其强制生成单个查询,但我想知道是否还有其他方法可以这样做。我正在寻找我们可以在实体级别做的事情以减少查询。
使用spring boot 2.1.5-RELEASE版本及相关依赖。
PS。和是@Data
Lombok@NoArgsConstructor
注释。
解决方案
最小的代码更改是使用 spring data 中的 ad-hoc EntityGraph 功能。只需覆盖PersonRepository
'sfindAll()
并用于@EntityGraph
配置图形。此图中的所有实体将一起获取。
public interface PersonRepository extends CrudRepository<Person, Long> {
@EntityGraph(attributePaths = { "password", "roles" })
public List<Person> findAll();
}
在幕后它的工作原理就像JOIN FETCH
. 只会生成带有 LEFT JOIN 的单个 SQL。
推荐阅读
- reactjs - React hooks 网站不断发送无限数量的 GET 请求
- flutter - 如何在 currentTab 上更改 TabItem 上的图标
- parsing - OpenCL:帮助解析 cl 代码以进行 JIT 编译
- javascript - 如何从 nuxt 插件发出事件?
- android - 数据绑定在动态fature模块中不起作用
- sql - 如何使用带有列名的like关键字在sqlite中查询?
- reactjs - 使用 react-snap 预渲染带有压缩(gzip)源的 React 应用程序
- pandas - 带有示例 2 数据帧的逐行连接
- python - Python:忽略 XML 文件中的 EOF
- html - html 字段演示中的 HTML 格式文本