Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate @ManyToMany delete relation

I have 2 entities: User and UsersList.

@Entity
@Table(name = "USERS")
public class User {
    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ManyToMany(cascade = CascadeType.REMOVE, mappedBy = "users")
    private List<UsersList> usersLists = new ArrayList<UsersList>();

    public List<UsersList> getUsersLists() {
        return usersLists;
    }

    public void setUsersLists(List<UsersList> usersLists) {
        this.usersLists = usersLists;
    }
}

and

@Entity
@Table(name = "USERS_LIST")
public class UsersList {
    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ManyToMany
    private List<User> users = new ArrayList<User>();

 public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

and code like this one:

// 1
List<User> dbUsers; // 3 the user instances are persisted in DB
UsersList usersList = new UsersList();
usersList.setUsers(dbUsers);

// 2 - now persist the usersList using hibernate...
saveWithHibernate(usersList); 

//3 - delete using a persisted user
deleteWithHibernate(dbUsers.get(0).getId());

where

deleteWithHibernate(Long id) {
        User usr = hibernateTemplate.get(User.class, id);
        hibernateTemplate.delete(usr);
}

In step 1 I have 3 rows in the USERS (USER_ID) table.

After step 2 (second comment) I have 1 row in the USERS_LIST (USERS_LIST_ID) table and into the join table USERS_LIST_USERS (USER_ID, USERS_LIST_ID) 3 rows.

What I want to achieve in step 3 is the following: when I delete one user from the table USERS - let's say user with USER_ID = 4, I want just the row with USER_ID = 4 from the join table to be deleted, and the others to remain.

Is there an annotation solution to my problem?

like image 745
Flueras Bogdan Avatar asked Aug 19 '09 11:08

Flueras Bogdan


People also ask

What is orphan removal in JPA?

The orphanRemoval attribute is going to instruct the JPA provider to trigger a remove entity state transition when a PostComment entity is no longer referenced by its parent Post entity.


1 Answers

What you need is the @JoinTable attribute:

Hibernate does not know that the many-to-many relations refer to each other and will probably create two join tables. If you specify the same @JoinTable on both sides of the relation it will work as expected.

Make sure that the joinColumn and the inverseJoinColumn are opposites on the opposing sides of the relation.

  • joinColumn on one side == inverseJoinColumn on other side
  • inverseJoinColumn on one side == joinColumn on other side

I hope this helps.

@Entity
public class Role extends Identifiable {

    @ManyToMany(cascade ={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(name="Role_Permission",
            joinColumns=@JoinColumn(name="Role_id"),
            inverseJoinColumns=@JoinColumn(name="Permission_id")
        )
    public List<Permission> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<Permission> permissions) {
        this.permissions = permissions;
    }
}

@Entity
public class Permission extends Identifiable {

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(name="Role_Permission",
            joinColumns=@JoinColumn(name="Permission_id"),
            inverseJoinColumns=@JoinColumn(name="Role_id")
        )
    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

}
like image 93
andersjanmyr Avatar answered Oct 04 '22 00:10

andersjanmyr