spring 如何使用Sping Boot JPA从具有@ManyToMany关系的任务中删除标记?

5uzkadbs  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(261)

我目前正在使用Java开发一个task/project/tags Web应用程序,广泛使用Sping Boot JPA(我对这个框架相对较新,所以请原谅我)。我已经在Task和Tag实体之间声明了@ManyToMany关系(定义如下)。
任务实体:

  1. @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
  2. @Entity()
  3. @Table(name = "tasks_dim")
  4. @Data
  5. @Builder
  6. @NoArgsConstructor
  7. @AllArgsConstructor
  8. public class Task {
  9. @Id
  10. @GeneratedValue(strategy = GenerationType.IDENTITY)
  11. @Column(updatable = false, nullable = false)
  12. private Long id;
  13. @Column(nullable = false)
  14. private String name;
  15. private String status;
  16. private String priority;
  17. @Column(name = "task_id_number", unique = true)
  18. private String taskIdNumber;
  19. @JsonIgnore
  20. @ManyToOne(optional = false)
  21. @JoinColumn(name = "user_id", referencedColumnName = "id")
  22. private User user;
  23. @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH})
  24. @JoinTable(name = "task_tags_dim",
  25. joinColumns = @JoinColumn(name = "task_id"),
  26. inverseJoinColumns = @JoinColumn(name = "tag_id"))
  27. private Set<Tag> tags = new LinkedHashSet<>();
  28. @Temporal(TemporalType.DATE)
  29. @Column(name = "due_date")
  30. private Date dueDate;
  31. public Task(String name, String status, String priority, User user) {
  32. setName(name);
  33. setDescription(description);
  34. setStatus(status);
  35. setPriority(priority);
  36. setTaskIdNumber(new TaskIdNumberBuilder().buildTaskIdNumber());
  37. setUser(user);
  38. setDueDate(dueDate);
  39. Timestamp currentTime = new Timestamp(new Date().getTime());
  40. setCreatedOn(currentTime);
  41. setLastUpdatedOn(currentTime);
  42. }

字符串
标记实体:

  1. @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
  2. @Entity()
  3. @Table(name = "tags_dim")
  4. @Data
  5. @Builder
  6. @NoArgsConstructor
  7. @AllArgsConstructor
  8. public class Tag {
  9. @Id
  10. @GeneratedValue(strategy = GenerationType.IDENTITY)
  11. @Column(updatable = false, nullable = false)
  12. private Long id;
  13. @Column(nullable = false, unique = true)
  14. private String name;
  15. @ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY)
  16. private Set<Task> tasks = new LinkedHashSet<>();
  17. public Tag(String name) {
  18. setName(name);
  19. }


但是,我的TagService类有问题,因为我无法在removeTag方法中使用getTags()。它返回一个空集合,所以即使我在create()和addTag()方法中添加标签,也没有什么可以删除的。如果我在create()中使用setTags(),我仍然无法从其他方法中的getTags()中获取任何数据。注意:

  • create()创建一个新的Tag对象,在新创建的Tag对象和它各自的任务之间添加一个链接,并将其保存到数据库中
  • addTag()在现有标记和给定的
  • task removeTag()删除一个正在执行的标记和给定的
  • task delete()删除所有标签(标签和任何任务之间的所有链接都应该被删除)
  1. @Service
  2. @Transactional
  3. public class TagService {
  4. @Autowired
  5. private TagRepository tagRepository;
  6. @Autowired
  7. private TaskRepository taskRepository;
  8. public Tag create(User user, Tag tag, Long task_id) {
  9. try {
  10. Optional<Task> optionalTask = taskRepository.findById(task_id);
  11. if (optionalTask.isPresent()) {
  12. Tag tagDetails = new Tag(tag.getName());
  13. Tag savedTag = tagRepository.save(tagDetails);
  14. Task currentTask = optionalTask.get();
  15. currentTask.getTags().add(savedTag);
  16. taskRepository.save(currentTask);
  17. return savedTag;
  18. }
  19. } catch(IllegalArgumentException e) {
  20. throw new IllegalArgumentException("Tag '" + tag.getName() + "' already exists.");
  21. }
  22. throw new NoSuchElementException("Task not found for the given task_id: " + task_id);
  23. }
  24. public Tag addTag(Tag tag, Long task_id) {
  25. Optional<Task> optionalTask = taskRepository.findById(task_id);
  26. if(optionalTask.isPresent()) {
  27. Task task = optionalTask.get();
  28. try {
  29. task.getTags().add(tag);
  30. taskRepository.save(task);
  31. return tag;
  32. } catch(Exception e) {
  33. throw new IllegalArgumentException("Tag '" + tag.getName() + "' is a duplicate entry.");
  34. }
  35. }
  36. throw new NoSuchElementException("Task not found for the given task_id: " + task_id);
  37. }
  38. public Set<Tag> getByTask(Long task_id) {
  39. Optional<Task> optionalTask = taskRepository.findById(task_id);
  40. if(optionalTask.isPresent()) {
  41. Set<Tag> myTags = optionalTask.get().getTags();
  42. for(Tag tag: myTags) {
  43. System.out.println(tag.getName());
  44. }
  45. return tagRepository.findByTasks(optionalTask.get());
  46. }
  47. throw new IllegalArgumentException("Task not found for the given task_id: " + task_id);
  48. }
  49. public Set<Tag> removeTag(Tag tag, Long task_id) {
  50. Optional<Task> optionalTask = taskRepository.findById(task_id);
  51. try {
  52. if(optionalTask.isPresent()) {
  53. Task currentTask = optionalTask.get();
  54. System.out.println(currentTask.getTags());
  55. return currentTask.getTags();
  56. }
  57. } catch(IllegalArgumentException e) {
  58. throw new IllegalArgumentException("Tag not found for the given task_id: " + task_id);
  59. }
  60. throw new NoSuchElementException("Request to remove tag from given task id '" + task_id + "' could not be processed");
  61. }
  62. public void delete(Tag tag) {
  63. tagRepository.deleteById(tag);
  64. }
  65. }


我试过使用Hibernate.initialize,但没有成功。'FetchType.LAZY'是这个用例的理想类型吗?

7dl7o3gd

7dl7o3gd1#

可选解决方案1:在Task类中使用@Getter和@Setter而不是@Data。
可选解决方案2:@Data annotation中的@ToString@EqualsAndHashCode annotation可能会导致问题。如果你想使用@Data,你应该覆盖toString(),equals()和hashCode()方法。
可选解决方案3:只需将@EqualsAndHashCode(of = "id")添加到Task类。

相关问题