Основная проблема с аутентификацией Spring - отложенная загрузка - PullRequest
0 голосов
/ 02 апреля 2020

Я использую аннотацию @AuthenticationPrincipal на уровне контроллера как таковую

@PutMapping(value = "add-book", consumes = "application/json")
public GenericResponse addBook(@AuthenticationPrincipal User user, @RequestBody Book book) {
    return userService.addBook(user, book);
}

и отправляю пользователя на сервисный уровень. Но, как видно из приведенной ниже модели пользователя, есть атрибут отложенной выборки, называемый bookList.

@Entity
@JsonIgnoreProperties(value = {"createdAt", "updatedAt", "roles", "enabled",
    "authorities", "credentialsNonExpired", "accountNonLocked", "accountNonExpired"})
@Data
@Accessors(chain = true)
public class User extends Base implements UserDetails, Serializable {

@Column(unique = true)
@Size(min = 4, max = 20)
@NotNull
private String username;

@NotNull
private String password;

@Column(unique = true)
@NotNull
@Email
private String email;

@ElementCollection(fetch = FetchType.EAGER)
private List<Role> roles = new ArrayList<>();

@JsonBackReference
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "book_id")
private List<Book> bookList = new ArrayList<>();

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return roles.stream().map(r -> new 
SimpleGrantedAuthority(r.toString())).collect(Collectors.toList());
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    return true;
}
}

Так что в этом случае пользователь, предоставленный аннотацией @AuthenticationPrincipal, не содержит атрибут books, поскольку он извлекается с отложенной выборкой. Итак, мне пришлось сделать следующее в сервисе:

public GenericResponse addBook(User user, Book book) {
    User userFetched = loadUserByUsername(user.getUsername());
    List<Book> bookList = userFetched.getBookList();
    bookList.add(book);
    if (userRepository.save(userFetched) != null) {
        return genericResponseService.createResponseNoError(userFetched);
    } else throw new RuntimeException();
}

Несмотря на то, что у меня есть пользователь, я использую loadByUsername, чтобы избежать исключения отложенной инициализации. Это хорошая практика или у меня есть лучший способ получить bookList пользователя?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...