Reputation: 5357
In a db, I have User
and Role
entities. The share a many-to-many relation as a Role
entity can be assigned to multiple User
entities and on the other hand a User
entity can be assigned to multiple Role
entities.
My entity classes look like this
UserEntity
@Entity
public class UserEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true, nullable = false)
private String username;
@ManyToMany
private Set<RoleEntity> roles;
...
}
RoleEntity
@Entity
public class RoleEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true, nullable = false)
private String name;
@ManyToMany(mappedBy = "roles")
private Set<UserEntity> users;
...
}
With this configuration I am able to map the entities with each other. I am also able to delete a User
entity. But I am not able to delete a Role
entity as long as a relation exists.
If I add cascade = CascadeType.REMOVE
the Role
gets deleted, but with it the User
too of course.
To only way to get this working currently is to define a @JoinTable
on both sides. But this seems more like a workaround. What am I doing wrong? As this is a regular use case, there got to be solution to this, although I haven found it yet...
Upvotes: 4
Views: 3416
Reputation: 1673
You need the join table, it's not a work around. Remember you are mapping your object oriented model to a relational model. The only way to express many-to-many relationship in the relational model is defining a @JoinTable.
UPDATE: Adding comment in the answer
You sould define the @JoinTable
just in one entity, for example UserEntity
and mappedBy="roles"
in RolesEntity
inherits the definitions of @JoinColumn
and @JoinTable
names.
Then you need to define the cascade operations you want to perform in both sides of the relationship.
In RoleEntity
@ManyToMany(mappedBy = "roles")
private Set<UserEntity> users;
In UserEntity
@ManyToMany
@JoinTable(...)
private Set<RoleEntity> roles;
Upvotes: 1