我使用 JPA 在 Spring Boot 应用程序中的两个实体之间添加多对多关系。我有以下映射: 任务类别:
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "task_tags_dim",
joinColumns = {@JoinColumn(name = "task_id")},
inverseJoinColumns = {@JoinColumn(name = "tag_id")})
private Set<Tag> tags;
标签类别:
@ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY)
private Set<Task> tasks;
最终目标是一个任务可以关联多个标签,一个标签可以关联多个任务。但是,似乎无论我尝试将标签添加到任务集多少次,任务集都不会“保存”之前添加的标签,因此
currentTask.getTags()
不会返回任何结果。我看过类似的帖子,但它对我的用例并没有多大帮助:Hibernate 多对多关系返回空集合
这是我的标签服务:
@Service
@Transactional
public class TagService {
@Autowired
private TagRepository tagRepository;
@Autowired
private TaskRepository taskRepository;
//create() will create a tag and link it to a specific task
public Tag create(Tag tag, Long task_id) {
try {
Optional<Task> optionalTask = taskRepository.findById(task_id);
if (optionalTask.isPresent()) {
Task currentTask = optionalTask.get();
Tag newTag = new Tag(tag.getName(), tag.getColor());
//currentTask.getTags().add(newTag);
//taskRepository.save(currentTask);
System.out.println(currentTask.getTags().size()); //always returns 0
Set<Tag> tags = currentTask.getTags();
tags.add(tag);
currentTask.setTags(tags);
taskRepository.save(currentTask);
return newTag;
}
} catch(IllegalArgumentException e) {
throw new IllegalArgumentException("Tag '" + tag.getName() + "' already exists.");
}
throw new NoSuchElementException("Task not found");
}
}
我在任务类中使用 Cascade.type 的方式有问题吗?
从 taskRepository.findById() 获取任务对象后,我尝试使用 getTags() 检索这些任务的标签,但没有返回任何结果。我还尝试将 Fetch 类型更改为 EAGER,但没有成功。
您的多对多关系是双向的。当您添加新的加入条目时,您必须将其添加到两侧(两个实体)。在 Post 实体中实现一个辅助方法,如下所示:
public void addTag(Tag tag) {
tags.add(tag);
tag.getTasks().add(this);
}
在服务类中,您将像这样调用此方法:
currentTask.addTag(newTag);
taskRepository.save(currentTask);
与此类似,您应该实现一个删除加入条目的方法:
public void removeTag(Tag tag) {
tags.remove(tag);
tag.getTasks().remove(this);
}
这样您就可以在一处实现,并且关系将正确同步。
基于:https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/