user3727777
user3727777

Reputation: 21

Using seperate OneToManys to create a ManyToMany Join table

I've got 2 models User and Exercise. Now any User can have any Exercise. It's a ManyToMany situation. I modeled it with @ManyToMany, but you can't have a duplicate entry in a ManyToMany. A User is likely to do multiple sets of one exercise so I duplicate entries are required. To get round this I created the join table separately called UserExerciseJoin. User and Exercise had ManyToOne relationships with the UserExerciseJoin model. Though this solved the multiple keys issue I now can't delete from the new table. I get an OptimisticLockException from some of the models associated to the Exercise.

My question is: Am I on the right path with the seperate table or is there something I can do to a standard @ManyToMany to make it accept duplicate entries?

Upvotes: 1

Views: 103

Answers (2)

Andrey Usov
Andrey Usov

Reputation: 1597

If I understand it right in your model, then yes, it is probably not the case for @ManyToMany. It seems to me that you can be better off with a meaningful entity like UserExerciseOccurrence that reference both a User and an Exercise and means a concrete exercise session.

You can also benefit from this approach if you need to save more info about a particular exercise session (like duration, etc).

@Entity
class UserExerciseOccurrence {
   @ManyToOne
   User user;

   @ManyToOne
   Exercise exercise;
}

@Entity
class User {
   @OneToMany(mappedBy="user", cascade=DELETE)
   Set<UserExerciseOccurrence> exerciseOccurrences;
}

@Entity
class Exercise {
   @OneToMany(mappedBy="exercise", cascade=DELETE)
   Set<UserExerciseOccurrence> exerciseOccurrences;
}

Upvotes: 2

rtruszk
rtruszk

Reputation: 3922

You are on the right path. You should have @OneToMany relation from User class and from Excercise class to this new entity. And in UserExerciseJoin you should have @ManyToOne relations.
So this code should look like this:

@Entity
User {
    @OneToMany(mappedBy="user")
    private List<UserExercise> userExercises;

    ....
}

@Entity
Excercise {
    @OneToMany(mappedBy="excercise")
    private List<UserExercise> userExercises;

    ....
}

@Entity
UserExercise
{
    @ManyToOne
    private User user;

    @ManyToOne
    private Excercise excercise;

    ...
}

You had an error when deleting this new entity. You had in on some entity related to excercise. It seems that this is because of cascades. You probably set cascades on fields of UserExerciseJoin class. If it was CascadeType.DELETE or CascadeType.ALL cascade then it caused deletion of related entities. So you shouldn't set cascades in UserExercise class. Then deleting of such entity will not cause a problem.

Upvotes: 1

Related Questions