I have a Spring project that uses JPA with Hibernate and MySQL database. Database includes three tables: Users, Roles, and many-to-many join table UserRoles. Below are the corresponding classes for the tables.
ApplicationUser.java
@Entity
@Table(name = "APPLICATION_USER")
public class ApplicationUser extends ExtAuditInfo {
public static final Long SYSTEM_USERID = 1000L;
@Id
@Column(name = "APPLICATION_USER_ID")
private long applicationUserId;
@Column(name = "LOGIN_NAME")
private String loginName;
@Column(name = "LAST_NAME")
private String lastName;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "MIDDLE_NAME")
private String middleName;
@OneToMany(mappedBy = "id.applicationUser", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<UserRole> roles =new ArrayList<>();
//get and set methods
Role.java
@Entity
@Table(name = "ROLE")
@NamedQueries({
@NamedQuery(name = "Role.getRoleById", query = "select r from Role r where r.roleId =:roleId"))}
public class Role extends AuditInfo {
@Id
@Column(name="ROLE_ID")
private long roleId;
@Column(name="ACTIVE_FLAG")
private String activeFlag;
@Column(name="ROLE_NAME")
private String roleName;
@OneToMany(mappedBy = "id.role", fetch = FetchType.LAZY)
private List<UserRole> users = new ArrayList<>();
//get and set methods
UserRole.java
@Entity
@AssociationOverrides({
@AssociationOverride(name = "id.applicationUser",
joinColumns = @JoinColumn(name = "APPLICATION_USER_ID")),
@AssociationOverride(name = "id.role",
joinColumns = @JoinColumn(name = "ROLE_ID")) })
@Table(name = "USER_ROLE")
public class UserRole extends ExtAuditInfo implements Serializable{
@EmbeddedId
private UserRoleID id = new UserRoleID();
@Column(name="USER_ROLE_VER")
private long userRoleVer;
public UserRole(){
}
@Transient
public ApplicationUser getApplicationUser() {
return this.id.getApplicationUser();
}
public void setApplicationUser(ApplicationUser applicationUser) {
this.id.setApplicationUser(applicationUser);
}
public long getUserRoleVer() {
return this.userRoleVer;
}
public void setUserRoleVer(long userRoleVer) {
this.userRoleVer = userRoleVer;
}
@Transient
public Role getRole() { return this.id.getRole(); }
public void setRole(Role role) { this.id.setRole(role); }
}
UserRoleID.java
@Embeddable
public class UserRoleID implements Serializable {
@ManyToOne(cascade = CascadeType.ALL)
private ApplicationUser applicationUser;
@ManyToOne(cascade = CascadeType.ALL)
private Role role;
private static final long serialVersionUID = 1L;
public UserRoleID() {
}
public ApplicationUser getApplicationUser() {
return this.applicationUser;
}
public void setApplicationUser(ApplicationUser applicationUser) {
this.applicationUser = applicationUser;
}
public Role getRole() {
return this.role;
}
public void setRole(Role role) {
this.role = role;
}
}
Now, when I create a sample user with viewer role, the record is being inserted into the Application_user and User_Role tables, but when I try to update the role of the user it is adding a new role to the user instead of updating the existing role.
This is what I'm doing
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void updateRole(ApplicationUser appUser, long roleId){
EntityManager em=getEntityManager();
TypedQuery<Role> query = em.createNamedQuery("Role.getRoleById", Role.class);
query.setParameter("roleId",roleId);
Role r = query.getSingleResult();
UserRole userRole= appUser.getRole().get(0);
userRole.setRole(r);
em.merge(userRole);
em.flush();
em.detach(userRole);
}
Any idea, what to do to update the existing role instead of creating a new role in user_role table?
You are assigning new role to user, so a new record is added in user_role table, and old user_role entry is deleted. That's the right behavior. So it's not you called "update the role of user".
Update: You should delete role manually when many-to-many relationship.
appUser.getRoles().remove(userRole);
em.remove(userRole);
UserRole newUserRole = new UserRole();
newUserRole.setRole(r);
appUser.getRoles().add(newUserRole);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.