如何在 Hibernate 中对同一个 table 上的 ManyToOne 和 ManyToMany 关系建模?

How to model a ManyToOne and ManyToMany relationship on the same table in Hibernate?

我想在 tables

之间创建以下关系

Tables -

所以,为了实现这种关系,我有两种方法。我想知道哪个更好用

方法一 在这种方法中,DietPlans table 将与 Owner table 建立 OneToMany 关系,与客户 table 建立 ManyToMany 关系。

Owner -

@Data
@Entity
public class Owner {

    @EmbeddedId
    private OwnerKey ownerId;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Customer> customers= new ArrayList<Customer>();


    @OneToMany(fetch = FetchType.LAZY, mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Diet> dietPlans = new ArrayList<Diet>();
}

Customer table -

   @Data
    @Entity
    public class Customer{

        @EmbeddedId
        private CustomerKey customerId;

        @ManyToOne(fetch = FetchType.LAZY, optional= false)
        private Owner owner;

        @ManyToMany(fetch = FetchType.LAZY, mappedBy = "subscribedCustomers")
        private List<Diet> subscribedDietPlans = new ArrayList<Diet>();
    }

Diet 计划如下 -

@Data
@Entity
public class Diet {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumns({
        @JoinColumn(.....
    })
    private Owner owner;

   @ManyToMany(fetch = FetchType.LAZY, optional = false)
    @JoinColumns({
        @JoinColumn.....)
    })
    private List<Customer> subscribedCustomers = new ArrayList<Customer>();

}

不应允许客户创建任何饮食计划,而应仅订阅其所有者创建的饮食计划

方法二 在这种方法中,我不会在 dietPlans table 和客户 table 之间建立多对多关系,而是创建一个单独的 SubscribedPlans table 来包含引用(外键)来自 DietPlans table。 SubscribedPlans table 将与客户 Table 建立多对一关系。这样,客户就不会订阅不存在的计划。

就简单性而言,两者中哪一个更好?另外,如果有更好的方法来做这个建模,请告诉我。

您问题的答案将取决于以下问题的答案

Do you see an immediate requirement where you would need to put more data against the user's subscribed plan? For example, say, the duration for which subscribed plan will be active, pricing for the plan etc.

如果答案是否定的,那么您只需要维护映射即可。在这种情况下,方法 1 效果更好。

如果答案是肯定的,那么您需要采用方法 2。因为 SubscribedPlan 实体会发展并包含用户订阅计划的相关详细信息,例如持续时间、价格(它将是价格的 FK计划table)等