I'm very new to Spring.
I'm trying to get a Page to return that to my front end. The AppUser has a lazy association with Role entity.
I'm getting a failed to lazily initialize a collection of role error.
Did a lot of research but I do not get the issue.
Let's see the code :
AppUser entity :
@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;
Controller method :
@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");
}
}
Service method :
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
@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);
}
Looking at the logs I can see the query runs :
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 ?
So I guess I'm not so far of a way to retrieve the full object but I'm really stuck now.
Appreciate if you can help on that matter.
Thanks.
finally found the way to do it.
@EntityGraph(attributePaths = {"appRoles", "grade"})
@Query(value = "FROM AppUser appuser")
Page<AppUser> findAllAppUserWithAllProperties(Example example, Pageable
pageable);
It sounds using EntityGraph will keep the lazy loading except when we specifically call that query.