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

I would like to create the following relationship between the tables

Tables –

  • Owner – Owner table contains details about owner.
  • DietPlans – DietPlans table contains all diet plans that can be created by the owner. A owner can create n number of diet plans but each diet plans belong to a single owner. Thus, it is a 1 to n relationship or One to many.
  • Customer – Customer is basically an entity that consumes the diet plans. In other words, I want the customers to subscribe to the already existing diet plans. As such my understanding is that, this subscribing to a diet plan by a customer will be a Many to One relationship. n number of customers can subscribe to n number of diet plans and vice versa. The customer also has a Many to One relationship with the owner.

So, in order to realise this relationship I have 2 approaches. I would like to know which one would work better.

Approach 1 In this approach the DietPlans table will have OneToMany relationship with the Owner table and ManyToMany relationship with the Customer table.

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

And the Diet plans would be as follows –

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

}

The customer should not be allowed to create any diet plans instead just subscribe to the diet plans created by their owner.

Approach 2 In this approach, instead of having the Many to many relationship between the dietPlans table and the Customer table, i will instead create a separate SubscribedPlans table which will contain reference (Foreign Key) from the DietPlans table. The SubscribedPlans table will have Many to One relationship with the Customer Table. In this way, the customer does not get to subscribe to a plan that does not exist.

Which of the 2 is better in terms of simplicity ? Also, if there is a better way to do this modelling, please let me know.

Answer

Answer to your question would depend on the answer to the following question

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.

If the answer is no, then you just need to maintain the mapping. In this case, approach 1 works better.

If the answer is yes, then you need to go with approach 2. Because SubscribedPlan entity will evolve and contain the user’s subscribed plan related details such as duration, price (its going to be FK of price plan table) etc.

Leave a Reply

Your email address will not be published. Required fields are marked *