如何在 Hibernate 中对同一个 table 上的 ManyToOne 和 ManyToMany 关系建模?
How to model a ManyToOne and ManyToMany relationship on the same table in Hibernate?
我想在 tables
之间创建以下关系
Tables -
- 所有者 - 所有者 table 包含有关所有者的详细信息。
- DietPlans - DietPlans table 包含所有者可以创建的所有饮食计划。所有者可以创建
n
个饮食计划,但每个饮食计划都属于一个所有者。因此,它是 1
到 n
的关系或一对多。
- 客户 - 客户基本上是一个消费饮食计划的实体。换句话说,我希望客户订阅已经存在的饮食计划。因此,我的理解是,客户订阅饮食计划将是多对一的关系。
n
数量的客户可以订阅 n
数量的饮食计划,反之亦然。
客户也与所有者具有多对一关系。
所以,为了实现这种关系,我有两种方法。我想知道哪个更好用
方法一
在这种方法中,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)等
我想在 tables
之间创建以下关系Tables -
- 所有者 - 所有者 table 包含有关所有者的详细信息。
- DietPlans - DietPlans table 包含所有者可以创建的所有饮食计划。所有者可以创建
n
个饮食计划,但每个饮食计划都属于一个所有者。因此,它是1
到n
的关系或一对多。 - 客户 - 客户基本上是一个消费饮食计划的实体。换句话说,我希望客户订阅已经存在的饮食计划。因此,我的理解是,客户订阅饮食计划将是多对一的关系。
n
数量的客户可以订阅n
数量的饮食计划,反之亦然。 客户也与所有者具有多对一关系。
所以,为了实现这种关系,我有两种方法。我想知道哪个更好用
方法一
在这种方法中,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)等