将级联类型删除应用于许多关系

发布于 2025-01-20 16:57:29 字数 1842 浏览 2 评论 0原文

我目前正在开发网络票务系统,并有可以存储我的机票数据的课程。每张票都可以具有与之关联的多个标签,并且要管理我创建标签编辑器的那些标签。这很好,只有一个删除选项仍缺少。到目前为止,大多数删除都没有解释该标签仍由另一张票参考,该票证需要先删除它。在找到解决方案的过程中,我遇到了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<>();
}

但这仍然不起作用。我是否需要在标签对象中参考所有门票?还是我可以以某种方式使用“反向删除”级联类型?

I'm currently developing a web ticket system, and have classes to store my ticket data. Every ticket can have multiple labels associated with it, and to manage those labels I created a label editor. This works just fine, only a delete option is still missing. Until now most deletes failed with the explaination that the label was still referenced to by another ticket, which required removing it first. In the process of finding a solution I came across CascadeType.DELETE, which seemed to do exactly what I was after.

However, since the ticket object contains a set of labels and not the other way round, every time I deleted a ticket, all the labels would disappear, instead of the other way round. After reading the docs for the CascadeType, this seemed obvious, but I am now clueless how to achieve the opposite effect. I thought of just creating a reference to all the tickets that are using my Label, although that seems like storing the same data twice.

My Ticket looks something like this:


@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<>();
}

And the labels like this:

@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<>();
}

but that still does not work. Do I even need a reference to all my Tickets in my Label object? Or can I somehow use a "reversed REMOVE" cascade type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

饮湿 2025-01-27 16:57:29

您的多对多映射意味着您有两个相交表票和ticket_labels。我敢打赌你不想要那个,你只需要一个。 For bidirectional mapping you may have:

public class TicketLabel {
//...
   @ManyToMany(mappedBy = "labels", cascade {CascadeType.MERGE, CascadeType.PERSIST})
   private Set<Ticket> tickets = new HashSet<>();
}
//...

and

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);
   }
// ...
}

You have to manually synchronize labels and tickets by helper remove and add methods as explained in

Your many-to-many mapping means that you have two intersection tables ticket and ticket_labels. I bet you don't want that, you need just one. For bidirectional mapping you may have:

public class TicketLabel {
//...
   @ManyToMany(mappedBy = "labels", cascade {CascadeType.MERGE, CascadeType.PERSIST})
   private Set<Ticket> tickets = new HashSet<>();
}
//...

and

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);
   }
// ...
}

You have to manually synchronize labels and tickets by helper remove and add methods as explained in this thread. To remove label you have to remove it from all the tickets. CascadeType.REMOVE will cause in this case the removal of the whole association.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文