我目前正在使用 Java 开发一个任务/项目/标签 Web 应用程序,并广泛使用 Spring Boot JPA(我对这个框架还比较陌生,所以请耐心等待)。我已经声明了任务和标签实体之间的 @ManyToMany 关系(定义如下)。
任务实体:
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@Entity()
@Table(name = "tasks_dim")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(updatable = false, nullable = false)
private Long id;
@Column(nullable = false)
private String name;
private String status;
private String priority;
@Column(name = "task_id_number", unique = true)
private String taskIdNumber;
@JsonIgnore
@ManyToOne(optional = false)
@JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH})
@JoinTable(name = "task_tags_dim",
joinColumns = @JoinColumn(name = "task_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
private Set<Tag> tags = new LinkedHashSet<>();
@Temporal(TemporalType.DATE)
@Column(name = "due_date")
private Date dueDate;
public Task(String name, String status, String priority, User user) {
setName(name);
setDescription(description);
setStatus(status);
setPriority(priority);
setTaskIdNumber(new TaskIdNumberBuilder().buildTaskIdNumber());
setUser(user);
setDueDate(dueDate);
Timestamp currentTime = new Timestamp(new Date().getTime());
setCreatedOn(currentTime);
setLastUpdatedOn(currentTime);
}
标签实体:
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@Entity()
@Table(name = "tags_dim")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(updatable = false, nullable = false)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY)
private Set<Task> tasks = new LinkedHashSet<>();
public Tag(String name) {
setName(name);
}
但是,我的 TagService 类遇到问题,因为我无法在 removeTag 方法中使用 getTags() 。它返回一个空集,因此即使我在 create() 和 addTag() 方法中添加标签,也无需删除任何内容。如果我在 create() 中使用 setTags(),我仍然无法从其他方法中的 getTags() 获取任何数据。 注:
@Service
@Transactional
public class TagService {
@Autowired
private TagRepository tagRepository;
@Autowired
private TaskRepository taskRepository;
public Tag create(User user, Tag tag, Long task_id) {
try {
Optional<Task> optionalTask = taskRepository.findById(task_id);
if (optionalTask.isPresent()) {
Tag tagDetails = new Tag(tag.getName());
Tag savedTag = tagRepository.save(tagDetails);
Task currentTask = optionalTask.get();
currentTask.getTags().add(savedTag);
taskRepository.save(currentTask);
return savedTag;
}
} catch(IllegalArgumentException e) {
throw new IllegalArgumentException("Tag '" + tag.getName() + "' already exists.");
}
throw new NoSuchElementException("Task not found for the given task_id: " + task_id);
}
public Tag addTag(Tag tag, Long task_id) {
Optional<Task> optionalTask = taskRepository.findById(task_id);
if(optionalTask.isPresent()) {
Task task = optionalTask.get();
try {
task.getTags().add(tag);
taskRepository.save(task);
return tag;
} catch(Exception e) {
throw new IllegalArgumentException("Tag '" + tag.getName() + "' is a duplicate entry.");
}
}
throw new NoSuchElementException("Task not found for the given task_id: " + task_id);
}
public Set<Tag> getByTask(Long task_id) {
Optional<Task> optionalTask = taskRepository.findById(task_id);
if(optionalTask.isPresent()) {
Set<Tag> myTags = optionalTask.get().getTags();
for(Tag tag: myTags) {
System.out.println(tag.getName());
}
return tagRepository.findByTasks(optionalTask.get());
}
throw new IllegalArgumentException("Task not found for the given task_id: " + task_id);
}
public Set<Tag> removeTag(Tag tag, Long task_id) {
Optional<Task> optionalTask = taskRepository.findById(task_id);
try {
if(optionalTask.isPresent()) {
Task currentTask = optionalTask.get();
System.out.println(currentTask.getTags());
return currentTask.getTags();
}
} catch(IllegalArgumentException e) {
throw new IllegalArgumentException("Tag not found for the given task_id: " + task_id);
}
throw new NoSuchElementException("Request to remove tag from given task id '" + task_id + "' could not be processed");
}
public void delete(Tag tag) {
tagRepository.deleteById(tag);
}
}
我尝试使用 Hibernate.initialize 但没有运气。 “FetchType.LAZY”是此用例的理想类型吗?
可选解决方案1:在Task类中使用@Getter和@Setter代替@Data。
可选解决方案 2:
@ToString
注释中的 @EqualsAndHashCode
和 @Data
注释可能会导致问题。如果你想使用 @Data
,你应该重写 toString()、equals() 和 hashCode() 方法。
可选解决方案 3:只需将
@EqualsAndHashCode(of = "id")
添加到 Task 类即可。