Herr Derb
Herr Derb

Reputation: 5357

JPA Many-to-Many relation: delete child entity not possible with active relation

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 Rolegets 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

Answers (1)

Rafael Guillen
Rafael Guillen

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

Related Questions