Spring - 获取加载惰性元素的实体页面

Spring - get a page of entity with lazy elements loaded

我对 Spring 很陌生。

我正在尝试将页面 return 发送到我的前端。 AppUser 与 Role 实体有惰性关联。

我收到一个未能延迟初始化角色集合的错误。

做了很多研究,但我没有得到这个问题。

让我们看看代码:

AppUser 实体:

@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "app_user")
public class AppUser {
    @Id
    @GeneratedValue
    @Column(name = "user_id")
    private UUID userId;

    @Column(name = "user_first_name")
    private String userFirstName;

    @Column(name = "user_last_name")
    @NonNull
    private String userLastName;

    @Column(name = "matricule")
    private String matricule;

    @Column(name = "email_address")
    private String emailAddress;

    @Column(name = "password")
    private String password;

    @EqualsAndHashCode.Exclude
    @ManyToOne
    @JoinColumn(name = "grade_id")
    private Grade grade;

    @EqualsAndHashCode.Exclude
    @ManyToMany
    @JoinTable(name = "user_role_association", joinColumns = @JoinColumn(name = "user_id"), 
inverseJoinColumns = @JoinColumn(name = "application_role_id"))
    private List<AppRole> appRoles;

控制器方法:

    @GetMapping(path = "user", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Page<AppUser>> getUserPage(@AuthenticationPrincipal UserDetail user,
                                                 @RequestParam("page") int page,
                                                 @RequestParam("size") int size,
                                                 @RequestParam(value = "sortDirection", 
required = false) String sortDirection,
                                                 @RequestParam(value = "sortField", required = 
false) String sortField) {
    log.info(String.format("User %s getting list of all users", user.getUsername()));
    try {
        final Page<AppUser> response = appUserService.getAll(page, size,sortDirection, 
sortField);
        return ResponseEntity.ok(response);
    } catch (Exception e) {
        log.error("Error fetching user page", e);
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Error fetching data");
    }
}

服务方式:

    public Page<AppUser> getAll(int page,
                            int size,
                            String sortDirection,
                            String sortField) {
    Pageable pageable;
    Sort sort;
    // sorting & pagination
    if (sortField != null && !sortField.isEmpty()) {
        sort = Sort.by(sortField);
        if (sortDirection != null && sortDirection.equals("desc")) {
            sort = sort.descending();
        }
    } else {
        sort = Sort.by("matricule").descending();
    }
    pageable = PageRequest.of(page, size, sort);

    return appUserRepository.findAllAppUserWithAllProperties(pageable);
}

存储库

@Repository
public interface AppUserRepository extends JpaRepository<AppUser, UUID> {
Optional<AppUser> findByUserId(UUID uuid);
AppUser findByMatricule(String matricule);

@Query(value = "SELECT u FROM AppUser u LEFT JOIN FETCH u.appRoles WHERE u.matricule = 
:matricule")
AppUser findAppUserWithAppRolesByMatricule(String matricule);

@Query(value = "SELECT u FROM AppUser u LEFT JOIN u.appRoles")
Page<AppUser> findAllAppUserWithAllProperties(Pageable pageable);

}

查看日志我可以看到查询运行:

SQL - select appuser0_.user_id as user_id1_0_, appuser0_.email_address as email_ad2_0_, 
appuser0_.grade_id as grade_id7_0_, appuser0_.matricule as matricul3_0_, appuser0_.password as 
password4_0_, appuser0_.user_first_name as user_fir5_0_, appuser0_.user_last_name as 
user_las6_0_ from rixheim.app_user appuser0_ left outer join rixheim.user_role_association 
approles1_ on appuser0_.user_id=approles1_.user_id left outer join rixheim.application_role 
approle2_ on approles1_.application_role_id=approle2_.application_role_id order by 
appuser0_.matricule desc limit ?

所以我想我还没有办法检索完整的对象,但我现在真的卡住了。

如果您能在这方面提供帮助,我们将不胜感激。

谢谢。

延迟关联是故意的还是可以更改?如果可以:

@EqualsAndHashCode.Exclude
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_role_association", joinColumns = @JoinColumn(name = "user_id"), 
inverseJoinColumns = @JoinColumn(name = "application_role_id"))
private List<AppRole> appRoles;

如果没有,您可以通过显式调用它来触发它们的加载,例如通过获取它们 appUser.getAppRoles()。它不漂亮,但应该可以。

终于找到方法了。

@EntityGraph(attributePaths = {"appRoles", "grade"})
@Query(value = "FROM AppUser appuser")
Page<AppUser> findAllAppUserWithAllProperties(Example example, Pageable 
pageable);

听起来使用 EntityGraph 将保持延迟加载,除非我们专门调用该查询。