JPA @OneToMany LAZY 关系的 Java Spring Boot 性能问题

问题描述 投票:0回答:1

我有一些

DepartmentView
与另一个视图UserDepartmentView
@OneToMany
关系,我的问题是当我尝试加载所有部门时需要太多时间。

在本地加载 600 个条目需要大约 4 秒,在生产环境中需要更多时间

我尝试使用

@EntityGraph 实现,但它并没有真正帮助我减少加载时间。

知道如何优化代码以缩短加载时间吗?

附注

DepartmentView

 还有更多其他属性,我只是没有在代码片段中列出

public List<DepartmentDTO> getDepartments() { Specification<DepartmentView> specification = getSomeSpecification(); List<DepartmentView> departmentViews = departmentViewRepo.findAll(specification); return departmentViews .stream() .map(DepartmentDTO::new) .toList(); } public interface DepartmentViewRepository extends CrudRepository<DepartmentView, String>, JpaSpecificationExecutor<DepartmentView> { @EntityGraph(attributePaths = {"users"}, type = EntityGraph.EntityGraphType.LOAD) List<DepartmentView> findAll(Specification<DepartmentView> specification); } @Entity @Immutable @Table(name = "department_view") public class DepartmentView implements Serializable { @Id @Column(name = "id", nullable = false) private String id; @Column(name = "name") private String name; @Column(name = "department_id") private String departmentId; @OneToMany(mappedBy = "department", cascade = CascadeType.ALL) @JsonBackReference @ToString.Exclude private List<UserDepartmentView> users; } @Entity @Immutable @Table(name = "user_department_view") public class UserDepartmentView { @Id @Column(name = "id", nullable = false) private String id; @Column(name = "name") private String name; @Column(name = "last_name") private String lastName; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_department_id", referencedColumnName = "department_id") @JsonIgnore @ToString.Exclude private DepartmentView department; } @AllArgsConstructor @NoArgsConstructor @Data public class DepartmentDTO { private String id; private String departmentId; private String name; private List<UserDTO> users; public DepartmentDTO(DepartmentView departmentView) { this.setId(departmentView.getId()); this.setDepartmentId(departmentView.getRequirementId()); this.setName(departmentView.getName()); this.setDataUsers(getUsers(departmentView)); } private static List<UserDTO> getUsers(DepartmentView departmentView) { return departmentView.getUsers() .stream() .map(UserDTO::new) .collect(Collectors.toList()); } }
    
java spring-boot jpa
1个回答
0
投票
正如 @Avinash Verma 所说,eager 可以帮助您解决性能问题。您应该考虑的另一件事是您的数据模型以及从数据库获取数据的方式。根据我的经验,尽可能不要使用 OneToMany 关系。在大多数情况下,当您从相反站点查看关系时,每个 OneToMany 都可以使用 ManyToOne 进行设计。

在您的示例中,如果您有部门实体和用户实体。一个部门可以有多个用户,因此部门实体中存在一对多的关系。用户只能属于一个部门,因此用户实体中存在多对一关系。因此,如果您想获取一个部门的所有用户,只需通过用户实体即可。最好只选择 *from User where Department = ?然后通过部门表选择它们,一对多正在执行此操作。

另一种方法是创建用户和部门之间的关系表,例如 user_department。然后你将有一个名为 f.e 的实体。 UserDepartmentRelation 其中您将有两个多对一关系(一个与用户,一个与部门)。因此,您可以使用此关系实体来获取一个部门的用户,并以某种方式将数据从关系实体映射到您的 dto 对象。该关系表和实体通常用于多对多关系,但也可以用于这种情况。

我可以看到的另一件事是,您似乎正在使用数据库中的视图。视图通常比仅通过连接进行选择要慢。您还可以使用列索引机制,这也可以帮助您消除性能问题。

© www.soinside.com 2019 - 2024. All rights reserved.