将级联类型删除应用于多对多关系
Apply cascade type delete to many to many relation
我目前正在开发一个网络票务系统,并且 类 可以存储我的票务数据。每张票都可以关联多个标签,为了管理这些标签,我创建了一个标签编辑器。这很好用,只是缺少删除选项。到目前为止,大多数删除都失败了,并解释说该标签仍被另一张票引用,这需要先将其删除。在寻找解决方案的过程中,我遇到了 CascadeType.DELETE,这似乎正是我所追求的。
但是,由于工单对象包含一组标签而不是反过来,所以每次我删除工单时,所有标签都会消失,而不是相反。在阅读了 CascadeType 的文档之后,这似乎是显而易见的,但我现在对如何实现相反的效果一无所知。我想创建一个对所有使用我的标签的票的引用,尽管这似乎将相同的数据存储了两次。
我的票看起来像这样:
@Entity
@Data
@NoArgsConstructor
public class Ticket {
@Id
@Column(length = 40)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false)
private String title;
@OneToMany(targetEntity = TicketEntry.class, mappedBy = "ticket", orphanRemoval = true, fetch = FetchType.EAGER)
private List<TicketEntry> entries = new ArrayList<>();
@Column
private Status status = Status.OPEN;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "ticket_labels",
joinColumns = { @JoinColumn(name = "ticket_id")},
inverseJoinColumns = { @JoinColumn(name = "label_id" )}
)
private Set<TicketLabel> labels = new HashSet<>();
}
还有这样的标签:
@Entity
@Data
@NoArgsConstructor
public class TicketLabel {
@Id
@Column(length = 40)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name = "";
@EqualsAndHashCode.Exclude
@ToString.Exclude
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@JoinTable(name = "ticket",
joinColumns = { @JoinColumn(name = "label_id")},
inverseJoinColumns = { @JoinColumn(name = "ticket_id" )}
)
private Set<Ticket> tickets = new HashSet<>();
}
但这仍然不起作用。我什至需要在我的 Label 对象中引用我的所有 Tickets 吗?或者我能以某种方式使用“反向删除”级联类型吗?
您的 many-to-many 映射意味着您有两个交集表 ticket 和 ticket_labels。我打赌你不想要那个,你只需要一个。对于双向映射,您可能有:
public class TicketLabel {
//...
@ManyToMany(mappedBy = "labels", cascade {CascadeType.MERGE, CascadeType.PERSIST})
private Set<Ticket> tickets = new HashSet<>();
}
//...
和
public class Ticket {
// ...
@ManyToMany
@JoinTable(name = "ticket_labels",
joinColumns = { @JoinColumn(name = "ticket_id")},
inverseJoinColumns = { @JoinColumn(name = "label_id" )}
)
private Set<TicketLabel> labels = new HashSet<>();
public void removeLabel(Label label) {
labels.remove(label);
label.getTickets().remove(this);
}
public void addLabel(Label label) {
labels.add(label);
label.getTickets().add(this);
}
// ...
}
您必须按照 中所述,通过帮助删除和添加方法手动同步标签和票证。要移除标签,您必须将其从所有门票中移除。 CascadeType.REMOVE 在这种情况下会导致删除整个关联。
我目前正在开发一个网络票务系统,并且 类 可以存储我的票务数据。每张票都可以关联多个标签,为了管理这些标签,我创建了一个标签编辑器。这很好用,只是缺少删除选项。到目前为止,大多数删除都失败了,并解释说该标签仍被另一张票引用,这需要先将其删除。在寻找解决方案的过程中,我遇到了 CascadeType.DELETE,这似乎正是我所追求的。
但是,由于工单对象包含一组标签而不是反过来,所以每次我删除工单时,所有标签都会消失,而不是相反。在阅读了 CascadeType 的文档之后,这似乎是显而易见的,但我现在对如何实现相反的效果一无所知。我想创建一个对所有使用我的标签的票的引用,尽管这似乎将相同的数据存储了两次。
我的票看起来像这样:
@Entity
@Data
@NoArgsConstructor
public class Ticket {
@Id
@Column(length = 40)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false)
private String title;
@OneToMany(targetEntity = TicketEntry.class, mappedBy = "ticket", orphanRemoval = true, fetch = FetchType.EAGER)
private List<TicketEntry> entries = new ArrayList<>();
@Column
private Status status = Status.OPEN;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "ticket_labels",
joinColumns = { @JoinColumn(name = "ticket_id")},
inverseJoinColumns = { @JoinColumn(name = "label_id" )}
)
private Set<TicketLabel> labels = new HashSet<>();
}
还有这样的标签:
@Entity
@Data
@NoArgsConstructor
public class TicketLabel {
@Id
@Column(length = 40)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name = "";
@EqualsAndHashCode.Exclude
@ToString.Exclude
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@JoinTable(name = "ticket",
joinColumns = { @JoinColumn(name = "label_id")},
inverseJoinColumns = { @JoinColumn(name = "ticket_id" )}
)
private Set<Ticket> tickets = new HashSet<>();
}
但这仍然不起作用。我什至需要在我的 Label 对象中引用我的所有 Tickets 吗?或者我能以某种方式使用“反向删除”级联类型吗?
您的 many-to-many 映射意味着您有两个交集表 ticket 和 ticket_labels。我打赌你不想要那个,你只需要一个。对于双向映射,您可能有:
public class TicketLabel {
//...
@ManyToMany(mappedBy = "labels", cascade {CascadeType.MERGE, CascadeType.PERSIST})
private Set<Ticket> tickets = new HashSet<>();
}
//...
和
public class Ticket {
// ...
@ManyToMany
@JoinTable(name = "ticket_labels",
joinColumns = { @JoinColumn(name = "ticket_id")},
inverseJoinColumns = { @JoinColumn(name = "label_id" )}
)
private Set<TicketLabel> labels = new HashSet<>();
public void removeLabel(Label label) {
labels.remove(label);
label.getTickets().remove(this);
}
public void addLabel(Label label) {
labels.add(label);
label.getTickets().add(this);
}
// ...
}
您必须按照