【问题标题】:Spring - get a page of entity with lazy elements loadedSpring - 获取加载了惰性元素的实体页面
【发布时间】:2021-11-08 22:16:44
【问题描述】:

我对 Spring 很陌生。

我正在尝试获取一个页面以将其返回到我的前端。 AppUser 与 Role 实体具有惰性关联。

我得到一个 failed to lazily initialize a collection of 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 ?

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

感谢您能在这件事上提供帮助。

谢谢。

【问题讨论】:

  • 不知道为什么编辑删除它,但我的问题是从“大家好”开始
  • @Query(value = "SELECT u FROM AppUser u LEFT JOIN u.appRoles") Page&lt;AppUser&gt; findAllAppUserWithAllProperties(Pageable pageable); 也应该是LEFT JOIN FETCH?
  • 嗨 Capricorn1,不,遗憾的是 FETCH 不能用于 Pageable 查询(不记得错误,但它不起作用,并且在该网站上发现您不应该使用 FETCH)。

标签: spring lazy-initialization pageable


【解决方案1】:

终于找到了办法。

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

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

【讨论】:

    【解决方案2】:

    懒惰的关联是故意的还是可以改变的?如果可以的话:

    @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()。它不漂亮,但它应该可以工作。

    【讨论】:

    • 嘿,是的,懒惰的联想是故意的。我可以尝试一下 Eager,但不是我的首选。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2022-06-10
    相关资源
    最近更新 更多