I have User entity and Role entity which are generated using JPA Tools. User and Role have many-to-many relationship. I use following code to insert admin, however, no data is inserted into user_role table. Also I notice role class has @JoinTable but user class does not have it. Are there differences?
private void addAdmin() {
User admin = new User();
admin.setDisplayName("admin");
Role role1 = new Role();
role1.setRole("ROLE_SUPER_ADMIN");
Role role2 = new Role();
role2.setRole("ROLE_END_USER");
List<Role> roles = new ArrayList<Role>();
roles.add(role1);
roles.add(role2);
admin.setRoles(roles);
userRepository.save(admin);
}
Following is my User class:
@Entity
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="display_name")
private String displayName;
//bi-directional many-to-many association to Role
@ManyToMany(mappedBy="users")
private List<Role> roles;
}
Following is my role class:
@Entity
@NamedQuery(name="Role.findAll", query="SELECT r FROM Role r")
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String role;
//bi-directional many-to-many association to User
@ManyToMany
@JoinTable(
name="user_role"
, joinColumns={
@JoinColumn(name="role_id")
}
, inverseJoinColumns={
@JoinColumn(name="user_id")
}
)
private List<User> users;
}
roles
association in the User
entity is the inverse side of the association (specified by mappedBy
). That means that it is the duty of Role
class to maintain the association, so to make the association changes persistent, you have to modify the owner side as well:
role1.getUsers().add(admin);
role2.getUsers().add(admin);
Anyway, it is a very good convention to always update both sides of bidirectional associations, so that the state of the inverse side also reflects the changes in the owner side. That's why it is a common practice to create helper methods that change both sides of the association:
@Entity
public class User {
//bi-directional many-to-many association to Role
@ManyToMany(mappedBy="users")
private List<Role> roles;
public void addRole(Role role) {
if (!roles.contains(role)) {
roles.add(role);
role.addUser(this);
}
}
}
@Entity
public class Role {
//bi-directional many-to-many association to User
@ManyToMany
@JoinTable(
...
)
private List<User> users;
public void addUser(User user) {
if (!users.contains(user)) {
users.add(user);
user.addRole(this);
}
}
}