Почему не присваивается связь many to many?
Добрый день.
Пытался разобраться, но что-то не сдюжил)
Хочу сделать REST API, чтобы запрос на логин оправлялся не через форму, а JSONом с фронта
При попытке появляется ошибка
user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); |
user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER")));
2021-11-16 07:30:02.743 ERROR 6941 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.example.notes.service.UserService.saveUser(UserService.java:57) ~[classes/:na]
57 строка UserService
user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); |
user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER")));
User
import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import javax.persistence.*; import java.util.Collection; import java.util.Set; @Data @Entity @Table(name = "t_user") public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; @ManyToMany(fetch = FetchType.EAGER) private Set<Role> roles; public User() { } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return getRoles(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } } |
import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import javax.persistence.*; import java.util.Collection; import java.util.Set; @Data @Entity @Table(name = "t_user") public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; @ManyToMany(fetch = FetchType.EAGER) private Set<Role> roles; public User() { } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return getRoles(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
Role
import lombok.Data; import org.springframework.security.core.GrantedAuthority; import javax.persistence.*; import java.util.Set; @Data @Entity @Table(name = "t_role") public class Role implements GrantedAuthority { @Id private Long id; private String name; @Transient @ManyToMany(mappedBy = "roles") private Set<User> users; public Role(){} public Role(Long id) { this.id = id; } public Role(Long id, String name) { this.id = id; this.name = name; } @Override public String getAuthority() { return getName(); } } |
import lombok.Data; import org.springframework.security.core.GrantedAuthority; import javax.persistence.*; import java.util.Set; @Data @Entity @Table(name = "t_role") public class Role implements GrantedAuthority { @Id private Long id; private String name; @Transient @ManyToMany(mappedBy = "roles") private Set<User> users; public Role(){} public Role(Long id) { this.id = id; } public Role(Long id, String name) { this.id = id; this.name = name; } @Override public String getAuthority() { return getName(); } }
UserService
import com.example.notes.dto.UserDto; import com.example.notes.entity.Role; import com.example.notes.entity.User; import com.example.notes.repository.RoleRepository; import com.example.notes.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.Collections; import java.util.List; import java.util.Optional; @Service public class UserService implements UserDetailsService { @PersistenceContext private EntityManager entityManager; @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired BCryptPasswordEncoder bCryptPasswordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } return user; } public User findUserById(Long id) { Optional<User> userFromDb = userRepository.findById(id); return userFromDb.orElse(new User()); } public List<User> allUsers() { return userRepository.findAll(); } public boolean saveUser(UserDto userDto) { User user = userRepository.findByUsername(userDto.getUsername()); if (user != null) { return false; } user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); user.setUsername(userDto.getUsername()); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); userRepository.save(user); return true; } public boolean deleteUser (Long id) { if (userRepository.findById(id).isPresent()) { userRepository.deleteById(id); return true; } return false; } public List<User> usergList (Long minId) { return entityManager.createQuery("SELECT u FROM User u WHERE u.id > :paramId", User.class) .setParameter("paramId", minId).getResultList(); } } |
import com.example.notes.dto.UserDto; import com.example.notes.entity.Role; import com.example.notes.entity.User; import com.example.notes.repository.RoleRepository; import com.example.notes.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.Collections; import java.util.List; import java.util.Optional; @Service public class UserService implements UserDetailsService { @PersistenceContext private EntityManager entityManager; @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired BCryptPasswordEncoder bCryptPasswordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } return user; } public User findUserById(Long id) { Optional<User> userFromDb = userRepository.findById(id); return userFromDb.orElse(new User()); } public List<User> allUsers() { return userRepository.findAll(); } public boolean saveUser(UserDto userDto) { User user = userRepository.findByUsername(userDto.getUsername()); if (user != null) { return false; } user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); user.setUsername(userDto.getUsername()); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); userRepository.save(user); return true; } public boolean deleteUser (Long id) { if (userRepository.findById(id).isPresent()) { userRepository.deleteById(id); return true; } return false; } public List<User> usergList (Long minId) { return entityManager.createQuery("SELECT u FROM User u WHERE u.id > :paramId", User.class) .setParameter("paramId", minId).getResultList(); } }
RegistrationController
import com.example.notes.dto.UserDto; import com.example.notes.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class RegistrationController { @Autowired private UserService userService; @PostMapping("/registration") public String addUser(@RequestBody UserDto userDto) { // if (!userDto.getPassword().equals(userDto.getPasswordConfirm())) { // return "Password not match"; // } // // if (!userService.saveUser(userDto)) { // return "User already exists"; // } userService.saveUser(userDto); return "redirect:/"; } } |
import com.example.notes.dto.UserDto; import com.example.notes.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class RegistrationController { @Autowired private UserService userService; @PostMapping("/registration") public String addUser(@RequestBody UserDto userDto) { // if (!userDto.getPassword().equals(userDto.getPasswordConfirm())) { // return "Password not match"; // } // // if (!userService.saveUser(userDto)) { // return "User already exists"; // } userService.saveUser(userDto); return "redirect:/"; } }
Что отправляю из Postman
{
"username": "username",
"password": 123123,
"passwordConfirm": 123123
}
Ссылка на гит:
https://github.com/Akella058/notes_api
Опирался на эту статью:
https://habr.com/ru/post/482552/
Ради интереса попробовал сделать все по статье и отправить то же самое из постмана
результат тот же
Дополнительно:
Добрый день.
Проблема вот, тут:
public boolean saveUser(UserDto userDto) { User user = userRepository.findByUsername(userDto.getUsername()); if (user != null) { return false; } user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); user.setUsername(userDto.getUsername()); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); userRepository.save(user); return true; } |
public boolean saveUser(UserDto userDto) { User user = userRepository.findByUsername(userDto.getUsername()); if (user != null) { return false; } user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); user.setUsername(userDto.getUsername()); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); userRepository.save(user); return true; }
Попробуйте так:
public boolean saveUser(UserDto userDto) { User userFromDB = userRepository.findByUsername(userDto.getUsername()); if (userFromDB != null) { return false; } User user = new User(); user.setUsername(userDto.getUsername()); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); userRepository.save(user); return true; } |
public boolean saveUser(UserDto userDto) { User userFromDB = userRepository.findByUsername(userDto.getUsername()); if (userFromDB != null) { return false; } User user = new User(); user.setUsername(userDto.getUsername()); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); user.setRoles(Collections.singleton(new Role(1L, "ROLE_USER"))); userRepository.save(user); return true; }
Подробнее про ManyToMany
https://vladmihalcea.com/the-best-way-to-use-the-m...
У вас даже в idea подсвечивается потенциальная проблема
- Одна и та же ошибка, одни и те же вопросы... https://qna.habr.com/q/1072824
Интересно, если ОНО САМО не исправится - товарищ в третий раз вопрос задаст? :-)
- Орхан Гасанлы, получается, если из бд пришло нулл, то в эту переменную мы уже ничего присвоить не можем?
- Заработало)
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос

Проблема, когда не присваивается связь many to many в базе данных, может возникать по нескольким причинам. Вот несколько возможных причин и способы их решения:
1. Неправильно настроены таблицы:
Убедитесь, что у вас есть таблица, которая соединяет две другие таблицы через внешние ключи. Например, если у вас есть таблица "users" и таблица "roles", и вы хотите установить отношение many-to-many между ними, создайте третью таблицу "user_roles", которая будет содержать внешние ключи на таблицы "users" и "roles".
2. Неправильно настроены отношения в ORM:
Если вы используете ORM (Object-Relational Mapping), убедитесь, что вы правильно настроили отношения между сущностями. Например, в случае с Laravel Eloquent, убедитесь, что вы используете методы `belongsToMany()` для описания отношения many-to-many.
3. Неправильно настроены модели:
Проверьте, что у ваших моделей правильно настроены связи многие ко многим. Убедитесь, что в методах модели правильно указаны названия таблиц и внешних ключей.
Приведу пример настройки связи many-to-many в Laravel Eloquent:
class User extends Model { public function roles() { return $this->belongsToMany(Role::class); } } class Role extends Model { public function users() { return $this->belongsToMany(User::class); } }
Если после проверки вы все еще столкнулись с проблемой, попробуйте выполнить миграции базы данных и перезагрузить кэш приложения. Возможно, проблема была вызвана некорректным кэшированием или неверными данными в базе.
Надеюсь, эти рекомендации помогут вам решить проблему с присваиванием связи many-to-many в вашем проекте. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их для получения более подробной помощи.