Spring Boot多对多双向关联中,POST书籍时无法更新关联表的问题求助
Spring Boot多对多双向关联中,POST书籍时无法更新关联表的问题求助
我是Spring Boot新手,最近在做一个书籍和作者的项目,需要实现一个作者可以有多本书,一本书也可以由多个作者合著的多对多关联功能。目前POST作者可以正常工作,但POST书籍的时候,虽然用户表和书籍表都能更新,但中间的关联表(USERS_BOOKS)没有同步更新,数据库用的是PostgreSQL。
下面是我的实现细节:
实体类代码
Users类
@Entity @Table @Getter @Setter @NoArgsConstructor public class Users { @Id @SequenceGenerator( name = "user_sequence", sequenceName = "user_sequence", allocationSize = 1 ) @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "user_sequence" ) private Long userId; private String password; private LocalDate dateOfBirth; private String fullName; private String email; @Enumerated(EnumType.STRING) private Roles role; @ManyToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = "USERS_BOOKS", joinColumns = { @JoinColumn (name = "User_id", referencedColumnName = "userId") }, inverseJoinColumns = { @JoinColumn(name = "BookId", referencedColumnName = "bookId") }) private Set<Book> books; public Users(String password, LocalDate dateOfBirth, String fullName, String email, Roles role){ this.password = password; this.dateOfBirth = dateOfBirth; this.fullName = fullName; this.email = email; this.role = role; } public Users(String password, LocalDate dateOfBirth, String fullName, String email, Set<Book> books){ this.password = password; this.dateOfBirth = dateOfBirth; this.fullName = fullName; this.email = email; this.books = books; } public void addBooks(Set<Book> books){ if(this.role == Roles.AUTHOR){ for(Book book : books) try{ this.books.add(book); book.addAuthors(Set.of(this)); } catch(Exception e){ System.out.println("Wrong type of object for a List of Book"); continue; } } else { throw new IllegalArgumentException("Non author users cannot hold books"); } } public void removeBooks(Set<Book> books){ for(Book book : books) for(Book user : this.books){ if (user.equals(book)) { this.books.remove(user); } else{ System.out.println("Book: "+book.getTitle()+ " is already not in set."); } } } }
Book类
@Table(name = "Books") @Entity @Setter @Getter @AllArgsConstructor @NoArgsConstructor public class Book { @Id @SequenceGenerator( name = "book_sequence", sequenceName = "book_sequence", allocationSize = 1 ) @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "book_sequence" ) private Long bookId; private String title; private LocalDate releaseDate; private String genresStr; @Column(columnDefinition = "text") private String content; @ManyToMany(mappedBy="books", fetch=FetchType.LAZY, cascade = CascadeType.ALL) private Set<Users> authors; public Book(String title, LocalDate releaseDate, String content, String genresStr){ this.genresStr = genresStr; this.title= title; this.releaseDate = releaseDate; this.content = content; } public Book(String title, LocalDate releaseDate, String content, String genresStr, Set<Users> authors){ this.genresStr = genresStr; this.title= title; this.releaseDate = releaseDate; this.content = content; this.authors = authors; } public void addAuthors(Set<Users> authors){ System.out.println("addAuthorsCalled"); for(Users author : authors) try{ this.authors.add(author); author.addBooks(Set.of(this)); author.setRole(Roles.AUTHOR); } catch(Exception e){ System.out.println("Wrong type of object for a List of Users"); } } public void removeAuthors(Set<Users> authors){ if(authors.size() == 1){ System.out.println("Can't delete all authors for certain book"); return; } for(Users author : authors) for(Users user : this.authors){ if (user.equals(author)) { this.authors.remove(user); } else{ System.out.println("User: "+author.getFullName()+ " is already not in set."); } } } }
控制器代码
BookController
@RestController @RequestMapping(path = "api/books") public class BookController { private final BookService bookService; private UserService userService; public BookController(@Autowired BookService bookService, UserService userService){ this.bookService = bookService; this.userService = userService; } @GetMapping public List<Book> getBooks(){ return bookService.getBooks(); } @PostMapping public void addBook(@RequestBody Book book){ if(!book.getAuthors().isEmpty()){ for(Users author : book.getAuthors()){ author.setRole(Roles.AUTHOR); userService.saveUser(author); } } bookService.saveBook(book); } @DeleteMapping(path="{bookId}") public void deleteBook(@PathVariable ("bookId") Long bookId){ bookService.deleteBook(bookId); } @PutMapping(path="{bookId}") public void updateBook( @PathVariable("bookId") Long bookId, @RequestParam(required = false) String title, @RequestParam(required = false) LocalDate releaseDate, @RequestParam(required = false) String content, @RequestParam(required = false) Set<Long> userIds ){ Set<Users> usersToAdd = null; if(userIds!=null){ usersToAdd = userService.getUsersById(userIds); } bookService.updateBook(bookId, title, releaseDate, content, usersToAdd); } @PutMapping(path = "/{bookId}/delAuthor") public void putMethodName( @PathVariable Long bookId, @RequestParam(required = true) Set<Long> userIds ){ Set<Users> usersToRemove = userService.getUsersById(userIds); bookService.removeAuthors(bookId, usersToRemove); } }
UserController
@RestController @RequestMapping(path = "api/users") public class UserController { private final UserService userService; public UserController(@Autowired UserService userService){ this.userService = userService; } @GetMapping public List<Users> getAllUsers() { return userService.getUsers(); } @PostMapping public void addNewUser(@RequestBody Users user) { userService.saveUser(user); } @DeleteMapping(path="{userId}") void deleteUser(@PathVariable ("userId") Long userId){ userService.deleteUser(userId); } @PutMapping(path="{userId}") void updateUser(@PathVariable ("userId") Long userId, @RequestParam(required = false) String fullName, @RequestParam(required = false) String password, @RequestParam(required = false) LocalDate dateOfBirth, @RequestParam(required = false) String email, @RequestParam(required = false) Set<Long> bookIds ){ userService.updateUser(userId, password, dateOfBirth, fullName, email, bookIds); } }
UserService代码
@Service public class UserService { private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); private final UserRepository userRepository; private BookRepository bookRepository; public UserService(@Autowired UserRepository userRepository, BookRepository bookRepository){ this.userRepository = userRepository; this.bookRepository = bookRepository; } public Users getUser(Long id){ return this.userRepository.getReferenceById(id); } public List<Users> getUsers(){ return this.userRepository.findAll(); } public Set<Users> getUsersById(Set<Long> userIds){ Set<Users> users = new HashSet<>(); for(Long userId : userIds) if(userId != null){ users.add(this.getUser(userId)); } return users; } public void saveUser(Users user){ Optional<Users> userEmailOptional = userRepository.findUserByEmail(user.getEmail()); if(userEmailOptional.isPresent()){ throw new IllegalStateException("This email already exists in database"); } if(user.getRole() == Roles.AUTHOR){ Optional<Users> authorByFullName = userRepository.findUserByFullName(user.getFullName()); if(authorByFullName.isPresent()){ throw new IllegalStateException("Authors cannot have the same name"); } } user.setPassword(encoder.encode(user.getPassword())); userRepository.save(user); } // 剩余代码省略(原内容截断) }
备注:内容来源于stack exchange,提问作者marioszap
相关产品推荐
相关产品推荐

