Поле Spring Boot не обновляется - PullRequest
2 голосов
/ 08 октября 2019

В моем User классе у меня есть это:

@ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
private List<ClassRoom> classRooms  = new ArrayList<>();

И в моем ClassRoom классе у меня есть это:

@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<User> admins = new ArrayList<>();

Теперь в моем UserControllerкласс, у меня есть:

@PostMapping("user/{id}/c")
User addClassRoom(@PathVariable Long id,@RequestBody ClassRoom newClassRoom)
{
    return repository.findById(id)
            .map(user -> {
                user.getClassRooms().add(newClassRoom);
                return repository.save(user);
            })
            .orElseGet(() -> {
                return null;
            });
}

И когда я отправил это curl -X POST -H "Content-Type: application/json" -d "{ }" http://localhost:8080/user/{id}/c

admins поле User всегда []

Вот снимок:

empty field spring boot in JSON

И у меня есть 4 таблицы, связанные с этим отображением:

ManyToMany empty auto table spring boot

Я пытался spring.jpa.hibernate.ddl-auto=create-drop в моих aplication.properties

Пустые таблицы:

  • CLASSROOM_ADMINS
  • CLASSROOM_USER
  • CLASS_ROOM_ADMINS

Только таблица, содержащая сопоставление:

  • USER_CLASS_ROOMS

Как мне решить эту проблему?

Вот все таблицы, связанные с отображением ManyToMany:

tables related to many to many-spring boot

1 Ответ

2 голосов
/ 08 октября 2019

В newClassRoom вам также нужно добавить существующий user, например: newClassRoom.getAdmins().add(user);

ОБНОВЛЕНИЕ

Я исправил и подтвердил, теперь долженработать.

Что было не так

Ошибка переполнения стека произошла из-за сериализации JSON - она ​​не имеет ничего общего с сохранением JPA - и это произошло потому, что Userи ClassRoom имеют ссылки друг на друга. Чтобы исправить это, я пометил поле admins с помощью @JsonIgnore для разрыва циклической ссылки.


Тем не менее решение не является оптимальным, поскольку пользователь получен за пределами границы транзакции, поэтому находится в режим отсоединения . Из-за этого метод repository.save вынужден сливать user в контекст постоянства. Чтобы избежать этих накладных расходов, я создал сервис с транзакционным методом для инкапсуляции всего (Второй коммит).

BTW

В Java есть некоторые соглашения о коде (например,имена пакетов в нижнем регистре и т. д.). Пожалуйста, проверьте Google Java Style Code

Вот Service:

/**
* @author Eugen Covaci {@literal eugen.covaci.q@gmail.com}
* Created on 10/8/2019
*/
@Service
public class UserService {

@Autowired
private UserRepository userRepository;

@Transactional
public User addClassRoom(Long userId, ClassRoom newClassRoom) {
    return userRepository.findById(userId)
            .map(user -> {
                user.getClassRooms().add(newClassRoom);
                newClassRoom.getAdmins().add(user);
                return userRepository.save(user);
            })
            .orElseGet(() -> {
                return null;
            });
}
}

И в Controller используйте это:

return userService.addClassRoom(id, newClassRoom);
...