В моем приложении у меня есть связь «многие ко многим» между сущностями «Пользователь» и «Предпочтения».Поскольку для таблицы объединения требуется дополнительный столбец, мне пришлось разбить его на 2 однозначных ассоциации:
Сущность пользователя:
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
public Set<UserPreference> getPreferences()
{
return preferences;
}
Сущность предпочтения:
@OneToMany(mappedBy = "preference", fetch = FetchType.EAGER)
public Set<UserPreference> getUserPreferences()
{
return userPreferences;
}
Сущность UserPreference:
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
public User getUser()
{
return user;
}
public void setUser(User user)
{
this.user = user;
}
@ManyToOne
@JoinColumn(name = "preference_id", nullable = false)
public Preference getPreference()
{
return preference;
}
public void setPreference(Preference preference)
{
this.preference = preference;
}
@Column(nullable = false, length = 25)
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
Чтобы обновить одно из предпочтений, я перебираю набор предпочтений пользователя и обновляю значение следующим образом:
@RequestMapping(value = {"/edit-{id}-preference"}, method = RequestMethod.POST)
public String updateUserPreference(@ModelAttribute("userPreference") UserPreference preference, BindingResult result, ModelMap model)
{
User loggedInUser = (User)session.getAttribute("loggedInUser");
for (UserPreference pref : loggedInUser.getPreferences())
{
if (Objects.equals(pref.getId(), preference.getId()))
{
pref.setValue(preference.getValue());
}
}
userService.update(loggedInUser);
return "redirect:/users/preferences";
}
Iподтвердили, что переменная пользователя, которую я пытаюсь обновить, действительно содержит новое значение после выполнения этого кода.Еще более странно, что значение обновляется на веб-странице, когда происходит перенаправление, но база данных НЕ обновляется!Это код, который я использую для обновления, этот класс помечен @Transactional, и любой другой вызов этого метода (например, для обновления роли пользователя) работает отлично:
@Override
public void update(User user)
{
User entity = dao.findById(user.getId());
if (entity != null)
{
entity.setUserId(user.getUserId());
entity.setPassword(user.getPassword());
entity.setFirstName(user.getFirstName());
entity.setLastName(user.getLastName());
entity.setRole(user.getRole());
entity.setPreferences(user.getPreferences());
}
}
Это действуеткак и кеш сессии hibernate имеет обновленное значение, но фактически не сохраняет его.Я использую этот же метод обновления стиля примерно для 30 других объектов, и все работает отлично.Это моя единственная ассоциация «многие ко многим», которую мне пришлось разбить на 2 ассоциации «один ко многим», поэтому мне не с чем сравнивать.
Я что-то не так делаю?Когда я создаю пользователя с новым HashSet и сохраняю его, значение правильно записывается в «таблицу соединений».
***** РЕДАКТИРОВАТЬ *****
Для сравненияэто код, который я использую для создания нового пользователя с настройками по умолчанию.Предпочтения уже существуют, но таблица соединений полностью пуста, и этот код правильно сохраняет сущности:
User user = new User();
user.setUserId("admin");
user.setPassword(crypter.encrypt("admin"));
user.setFirstName("admin");
user.setLastName("admin");
user.setRole(roleService.findByName("Admin"));
Set<UserPreference> userPreferences = new HashSet<>();
Preference preference = preferenceService.findByName("anchorPage");
UserPreference userPreference = new UserPreference();
userPreference.setUser(user);
userPreference.setPreference(preference);
userPreference.setValue("System Statistics");
userPreferences.add(userPreference);
preference = preferenceService.findByName("showOnlyActivePatients");
userPreference = new UserPreference();
userPreference.setUser(user);
userPreference.setPreference(preference);
userPreference.setValue("true");
userPreferences.add(userPreference);
user.setPreferences(userPreferences);
userService.save(user);
Спасибо