Reputation: 171
I know only basics of DB and JPA/Hibernate. I have to manage a User table, where a user can have many roles. The roles are contained in a catalog table which in my User formulary i do not pretend to manage/modify, i just need the catalog values as a reference to add or delete to my user. I think the best approach would be to create a relationship table between User and Role to hold the users and their roles 'User_Roles' (unless there is a more efficient approach).
I am not allowed to modify the Role entity since it is used for different purposes in a lot of other areas of my app that are independent of the User table.
I've seen a lot of examples but I still do not know which one exactly aplies to my specific needs. How can I map my User and its roles in a sigle Entity with JPA and Hibernate?
Maybe the next image describes better what I want:
Thank you very much in advance for your answers.
Upvotes: 1
Views: 2202
Reputation: 2194
For the sake of simplicity: In this way is more flexible, in case of adding new attribure on the join table
@Table(name = "User")
public class User {
@OneToMany(mappedBy = "user")
Set<UserRoles> userRoles;
}
@Table(name = "Role")
public class Role {
@OneToMany(mappedBy = "role")
Set<UserRoles> userRoles;
}
@Table(name = "user_roles")
public class UserRoles {
@ManyToOne
@JoinColumn(name = "user_id")
User user;
@ManyToOne
@JoinColumn(name = "role_id")
Role role;
}
OBS: remember to use HashSet
Upvotes: 0
Reputation: 23
As per your above screen, what I understood user can be assigned more than 1 role. i.e. 1 user can be mapped to multiple role and 1 role can be mapped to multiple users.
Hence relationship between user and role is many to many.
many to many relationship can be achieved using third table which is called mapping table.
so , we have following tables in your example :-
user
user_roles
role
@Entity
@Table(name = "user")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
@Id
@SequenceGenerator(name = "USER_ID_GENERATOR", sequenceName = "USER_SEQ",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID_GENERATOR")
@Column(name = "user_id")
private Long userId;
@OneToOne
@JoinColumn(name = "persion_id")
private person person;`
enter code
here`
@Basic
@Column(name = "date")
private Date date;
@Basic
@Column(name = "observations")
private String observations;
@Basic
@Column(name = "text")
private String text;
@JsonIgnore
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<UserRoles> users = new ArrayList<>();
}
@Entity @Table(name = "role") @JsonInclude(JsonInclude.Include.NON_NULL) public class Role {
@Id
@SequenceGenerator(name = "ROLE_ID_GENERATOR", sequenceName = "ROLE_SEQ",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ROLE_ID_GENERATOR")
@Column(name = "role_id")
private Long roleId;
@Basic
@Column(name = "id1")
private Long idOne;
@Basic
@Column(name = "id1")
private Long idTwo;
@Basic
@Column(name = "id1")
private Long idThree;
@Basic
@Column(name = "text")
private String text;
@JsonIgnore
@OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
private List<UserRoles> users = new ArrayList<>();
}
@Entity @Getter @Setter @Table(name = "user_roles") @JsonInclude(JsonInclude.Include.NON_NULL) @Audited public class UserRoles {
private static final long serialVersionUID = 1L;
@EmbeddedId
UserRolesKey userRoleId;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("role_id")
@JoinColumn(name = "role_id")
Roles role;
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("user_id")
@JoinColumn(user_id)
User user;
@PrePersist
private void prePersist() {
super.onPrePersist();
if (this.getId() == null) {
UserRolesKey mapKey = new UserRolesKey();
mapKey.setRoleId(this.getRole().getRoleId());
mapKey.setUserRoleId(this.getUser().getUserId());
this.setId(mapKey);
}
}
}
While saving you just need to populate user entity with all the uaerRoles mapping entity and persist it. jpa will save all the details.
while updating role assign to user you need to fetch the user entity and update the mapping by adding new userRoles entity and nullifying the while is going to be removed.
Upvotes: 0
Reputation: 31
In your case you have to use @ManyToMany to associate both tables.
That should look at this:
@Entity
@Table(name = "User")
public class User {
...
@ManyToMany
@JoinTable(name = "User_Roles", joinColumn = "id_person")
private Set<Role> roles = new HashSet<>;
}
@Entity
@Table(name = "Role")
public class Role {
...
@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<>;
}
Upvotes: 3
Reputation: 26026
What you're describing is a one-to-many relationship but it's between User
and the joining table - User_Roles
. Since there is not much you can do to avoid the joining table, the best thing would be to use @ManyToMany
with @JoinTable
annotations to map the relationship. Remember to use Set
instead of List
. You don't need an entity for the joinint table then.
You can find a discussion about this topic in this blog post.
Upvotes: 2