Richard Avalos Richard Avalos - 4 months ago 31
MySQL Question

Hibernate user model not saving user-roles and role

Whenever I try to save a user to my MySql database, it is only saving data to the users table and not the roles-user and role table. Some help would be greatly appreciated.

(Each user has many roles and each role can belong to many users)

I have 3 tables in my database:

users: (id,username)
roles_users: (user_id, role_id)
roles: (id,role)


followed by two Hibernate entities:

This is my user model:

@Entity(name = "users")
public class User{

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;

@ManyToMany(mappedBy = "users", cascade = CascadeType.PERSIST)
private Set<Role> roles;

public Long getId() {
return id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public Set<Role> getRoles() {
if (roles == null) {
roles = new HashSet();
}
return roles;
}

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


This is my Role model:

@Entity(name = "roles")
public class Role {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "roles_users",
joinColumns = @JoinColumn(name = "role_id"),
inverseJoinColumns = @JoinColumn(name = "user_id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"role_id", "user_id"})})
private Set<User> users;

public Long getId() {
return id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<User> getUsers() {
if (users == null) {
users = new HashSet();
}
return users;
}

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


This is the code I use to save a user and its role(s):

User user = new User();
Role role = new Role();
Set<User> userSet = new HashSet();
Set<Role> roleSet = new HashSet();

user.setUsername("Peter");
role.setName("ROLE_ADMIN");
userSet.add(user);
roleSet.add(role);

role.setUsers(userSet);
user.setRoles(roleSet);

userService.saveUser(user);

Answer

The reason you observe this is because Role is the entity that manages the @ManyToMany relation between it and User but you're not updating the Role object in your code. I'd probably argue that is backward and that a User should probably own the relationship.

If you think about it, you create Role objects separately and later assign them to various User objects, as your code illustrates. So it would make sense that User owns that relationship.

// Transaction 1
Role role = new Role( "ADMIN" );
session.save( role );

// Transaction 2
User user = new User( "Naros" );
user.getRoles().add( roleService.getRoleByName( "ADMIN" ) );
session.save( user );