I have tables User, Roles, Groups and a join table GroupRoles. A user can have many Roles (some of which are not group specific), and a Group can have many roles. Since Roles can be group related I need to associate a groupID with them and hence GroupRoles has a unique key of userID, groupID and roleID. I need userID as part of the key as I need to know what Roles are associated to a user. In hibernate is mapping a unique key like this the same as mapping a composite key, where I would have something along the lines of
#Embeddable
public class GroupRoleKey implements Serializable {
#Column(name="userID")
private Long userID;
#Column(name="groupID")
private Long groupID;
#Column(name="roleID")
private Long roleID;
protected GroupRoleKey(){}
public GroupRoleKey(Long userID, Long roleID, Long groupID) {
this.userID = userID;
this.roleID = roleID;
this.groupID = groupID
}
Honestly I'm not sure if this is even the best way to represent the User - Role - Group relation, any advice would be appreciated. I need to display a Users Roles within each group they belong to, for example I may want to display Bob's Roles Admin and Teacher for Group 1 and role Group Admin for group 2. I need to know which roles correspond to what group and what roles correspond to what user.
EDIT:
Group Entity:
#Table(name="FocusGroups")
#Entity
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "groupID")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long groupID;
private String groupName;
#ManyToMany
#JoinTable(name = "GroupMembers",
joinColumns = #JoinColumn(
name = "groupID"),
inverseJoinColumns = #JoinColumn(
name = "userID"))
private Set<User> groupMembers = new HashSet<>();
#ManyToMany
#JoinTable(name = "GroupRoles",
joinColumns =
#JoinColumn(
name = "groupID"),
inverseJoinColumns = #JoinColumn(
name = "roleID"))
private Set<Role> roles = new HashSet<>();
#ManyToOne(fetch = FetchType.EAGER, optional = true)
#JoinColumn(name="frameworkID", nullable = true)
private Framework framework;
public Group(){}
public Group(String groupName, Set<User> groupMembers, Framework framework) {
this.groupName = groupName;
this.groupMembers = groupMembers;
this.framework = framework;
}
public Long getGroupID() {
return groupID;
}
public void setGroupID(Long groupID) {
this.groupID = groupID;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public Set<User> getGroupMembers() {
return groupMembers;
}
public void setGroupMembers(Set<User> groupMembers) {
this.groupMembers = groupMembers;
}
public void addMembers(Set<User> groupMembers){
this.groupMembers.addAll(groupMembers);
}
public void addMember(User groupMember){
this.groupMembers.add(groupMember);
}
public String groupMembersToString(){
String out = "";
int count = 0;
if(groupMembers.size() > 0){
for(User user: groupMembers){
if(count >= 1){
out += ", ";
}
out += user.getUsername();
count++;
}
}else{
out = "No members";
}
return out;
}
public boolean hasMember(String groupMemberName) {
for (User member : this.groupMembers) {
if (member.getUsername().equals(groupMemberName)) {
return true;
}
}
return false;
}
public User getGroupMember(String groupMemberName){
for(User member: this.groupMembers){
if(member.getUsername().equals(groupMemberName)){
return member;
}
}
return null;
}
public Framework getFramework() {
return framework;
}
public void setFramework(Framework framework) {
this.framework = framework;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role:
#Entity
#Table(name = "Roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long roleID;
private String roleName;
#ManyToMany
#JoinTable(name = "GroupRoles",
joinColumns =
#JoinColumn(
name = "roleID"),
inverseJoinColumns = #JoinColumn(
name = "groupID", nullable = true))
private Set<Group> groups = new HashSet<>();
protected Role(){}
public Role(String roleName){
this.roleName = roleName;
}
public Long getId() {
return roleID;
}
public void setId(Long id) {
this.roleID = id;
}
public String getName() {
return roleName;
}
public void setName(String roleName) {
this.roleName = roleName;
}
}
User:
#Table(name="Users")
#Entity
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(
name = "userRating",
procedureName = "CalculateUserRating",
parameters = {
#StoredProcedureParameter(
name = "userID",
type = Long.class,
mode = ParameterMode.IN),
#StoredProcedureParameter(
name = "focusID",
type = Long.class,
mode = ParameterMode.IN),
#StoredProcedureParameter(
name = "userRating",
type = BigDecimal.class,
mode = ParameterMode.OUT)
})
})
//store a base rating?
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long userID;
#Column(name = "userHashedPassword")
private String password;
#Column(name = "userName")
private String userName;
#Column(name = "userEmail")
private String email;
#ManyToMany
#JoinTable(name = "GroupMembers",
joinColumns = #JoinColumn(
name = "userID"),
inverseJoinColumns = #JoinColumn(
name = "groupID"))
private Set<Group> usersGroups = new HashSet<>();
#ManyToMany
#JoinTable(name = "UserRoles",
joinColumns = #JoinColumn(
name = "userID"),
inverseJoinColumns = #JoinColumn(
name = "roleID"))
private Set<Role> roles = new HashSet<>();
#OneToMany(mappedBy = "user")
private Set<Rating> ratings;
protected User(){}
public User(String userHashedPassword, String userName, String email, Set<Role> roles){
this.password = userHashedPassword;
this.userName = userName;
this.email = email;
this.roles = roles;
}
public User(String userName, String userHashedPassword){
this.userName = userName;
this.password = userHashedPassword;
}
public Long getUserId() {
return userID;
}
public void setId(Long userID) {
this.userID = userID;
}
public String getPassword(){
return password;
}
public void setPassword(String password){
this.password = password;
}
public String getUsername() {
return userName;
}
public void setUsername(String name) {
this.userName = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public Set<Rating> getRatings() {
return ratings;
}
public void setRatings(Set<Rating> ratings) {
this.ratings = ratings;
}
public String rolesToString(){
String outputRoles = "";
int count = 0;
for(Role role: roles){
if(count >= 1){
outputRoles += ", ";
}
outputRoles += role.getName();
count++;
}
return outputRoles;
}
public void removeRole(Role role){
this.roles.remove(role);
}
public Set<Group> getGroups() {
return usersGroups;
}
public void addGroup(Group group) {
this.usersGroups.add(group);
}
public void addGroups(Set<Group> groups) {
this.usersGroups.addAll(groups);
}
public Set<Group> getUsersGroups() {
return usersGroups;
}
public void setUsersGroups(Set<Group> usersGroups) {
this.usersGroups = usersGroups;
}
public String groupsToString(){
String outputGroups = "";
int count = 0;
if(usersGroups.size() > 0){
for(Group group: usersGroups){
if(count >= 1){
outputGroups += ", ";
}
outputGroups += group.getGroupName();
count++;
}
}else{
outputGroups = "None";
}
return outputGroups;
}
}
Related
i'm new in spring.I have a project that name is SampleStore. some entities created in my projects, such as User, UserRole, Product, Orders, CartItem and .... but i have a problem. when i try add new user app does it without error and new record inserted in databse. but when i try to insert new order i'll get error.
User.java
#Entity
#Table(name = "users")
public class User implements Serializable, UserDetails {
private static final long serialVersionUID = -8245107356306518473L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "username", nullable = false, unique = true, length = 50)
private String username;
#Column(name = "password", nullable = false, length = 60)
private String password;
#Column(name = "enabled", nullable = true, columnDefinition = "tinyint(1) default 1")
private boolean enabled;
#Column(name = "expired", nullable = true, columnDefinition = "tinyint(1) default 1")
private boolean accountNonExpired;
#Column(name = "locked", nullable = true, columnDefinition = "tinyint(1) default 1")
private boolean accountNonLocked;
#Column(name = "credential", nullable = true, columnDefinition = "tinyint(1) default 1")
private boolean credentialsNonExpired;
#Column(name = "gender", nullable = true)
private char gender;
#Column(name = "address", nullable = true)
private String address;
#Column(name = "phonenumber", nullable = true)
private String phoneNumber;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
private Set<UserRole> userRoles = new HashSet<UserRole>(0);
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
private List<Comment> comments = new ArrayList<Comment>();
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
private List<Orders> orders = new ArrayList<Orders>();
public User() {
}
public User(String username, String password, boolean enabled) {
this.username = username;
this.password = password;
this.enabled = enabled;
}
public User(String username, String password, boolean enabled, Set<UserRole> userRoles) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.userRoles = userRoles;
}
public User(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked, Set<UserRole> authorities) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.userRoles = authorities;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
#Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", enabled=" + enabled
+ ", gender=" + gender + ", address=" + address + ", phoneNumber=" + phoneNumber + ", userRoles="
+ userRoles + "]";
}
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(setAuths);
return result;
}
public boolean isAccountNonExpired() {
return accountNonExpired;
}
public boolean isAccountNonLocked() {
return accountNonLocked;
}
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
public void setAccountNonExpired(boolean accountNonExpired) {
this.accountNonExpired = accountNonExpired;
}
public void setAccountNonLocked(boolean accountNonLocked) {
this.accountNonLocked = accountNonLocked;
}
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
this.credentialsNonExpired = credentialsNonExpired;
}
}
UserRole.java
#Entity
#Table(name = "user_roles", uniqueConstraints = #UniqueConstraint(columnNames = { "username", "role" }))
public class UserRole {
private Integer userRoleId;
private User user;
private String role;
public UserRole() {
}
public UserRole(User user, String role) {
this.user = user;
this.role = role;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_role_id", unique = true, nullable = false)
public Integer getUserRoleId() {
return this.userRoleId;
}
public void setUserRoleId(Integer userRoleId) {
this.userRoleId = userRoleId;
}
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "username", nullable = false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "role", nullable = false, length = 45)
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
}
Orders.java
#Entity
#Table(name = "orders")
public class Orders implements Serializable {
private static final long serialVersionUID = -3672662224925418969L;
#Id
#Column(name = "ord_id", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#DateTimeFormat(pattern = "yyyy-mm-dd")
#Column(name = "orderDate", nullable = false)
private Date orderDate;
#DateTimeFormat(pattern = "yyyy-mm-dd")
#Column(name = "delivery", nullable = false)
private Date deliveryDate;
#Column(name = "success", nullable = true, columnDefinition = "tinyint(1) default 0")
private boolean success;
#Column(name = "cancel", nullable = true, columnDefinition = "tinyint(1) default 0")
private boolean canceled;
#Column(name = "cause", nullable = true)
private String cancelCause;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "order")
private List<CartItem> items = new ArrayList<CartItem>();
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="username",nullable=false)
private User user;
public Orders() {
}
public Orders(Date deliveryDate, List<CartItem> items, User user) {
this.orderDate = new Date();
this.deliveryDate = deliveryDate;
this.items = items;
this.user = user;
}
public Orders(List<CartItem> items, User user) {
this.orderDate = new Date();
this.items = items;
this.user = user;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
public Date getDeliveryDate() {
return deliveryDate;
}
public void setDeliveryDate(Date deliveryDate) {
this.deliveryDate = deliveryDate;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public boolean isCanceled() {
return canceled;
}
public void setCanceled(boolean canceled) {
this.canceled = canceled;
}
public String getCancelCause() {
return cancelCause;
}
public void setCancelCause(String cancelCause) {
this.cancelCause = cancelCause;
}
public List<CartItem> getItems() {
return items;
}
public void setItems(List<CartItem> items) {
this.items = items;
}
}
CartItem.java
#Entity
#Table(name = "saleitems", uniqueConstraints = {})
public class CartItem implements Serializable {
private static final long serialVersionUID = 7968604053015663078L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
private Long id;
#Column(name = "prd_id", nullable = false)
private Product product;
#Column(name = "quantity", nullable = false, columnDefinition = "int(11) default 1")
private Integer quantity;
#Column(name = "totalprice", nullable = false)
private BigDecimal totalprice;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "orderid", nullable = false)
private Orders order;
public CartItem(Product product, Integer quantity) {
this.product = product;
this.quantity = quantity;
setTotalprice();
}
public CartItem() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public BigDecimal getTotalprice() {
return totalprice;
}
public void setTotalprice() {
this.totalprice = getProduct().getPrice().multiply(new BigDecimal(getQuantity()));
}
public Orders getOrder() {
return order;
}
public void setOrder(Orders order) {
this.order = order;
}
}
here one part of my controller code that user to save new user and save new order.
#RequestMapping(value = "/saveuser", method = RequestMethod.POST)
public ModelAndView saveNewUser(#ModelAttribute User user) {
ModelAndView model = new ModelAndView();
user.setEnabled(true);
user.setAccountNonExpired(true);
user.setAccountNonLocked(true);
user.setCredentialsNonExpired(true);
UserRole role = new UserRole(user, "ROLE_USER");
Set<UserRole> roles = new HashSet<UserRole>();
roles.add(role);
user.setUserRoles(roles);
String result = userService.addUser(user);
if (!result.toLowerCase().startsWith("error")) {
model.setViewName("loginForm");
} else {
model.setViewName("newuser");
model.addObject("error", result);
}
return model;
}
#SuppressWarnings("unchecked")
#RequestMapping(value = "/store/addorder", method = RequestMethod.GET)
public ModelAndView addOrder(HttpSession session) {
ModelAndView model = new ModelAndView();
// create list of products that we have to add in orders
System.err.println("item get to retrieving---------------");
List<CartItem> items = (List<CartItem>) session.getAttribute("cart");
for (CartItem cartItem : items) {
System.err.println(cartItem.getProduct());
}
// find user by username to set orders userinfo
System.err.println("user information get to retriving---------------");
String username = SecurityContextHolder.getContext().getAuthentication().getName();
User user = userService.findByUsername(username);
System.err.println(user);
// new order generated and setter methods invoke
System.err.println("new order generated-------------------");
Orders order = new Orders(items, user);
Date d = new Date();
Date delivery = StoreUtils.deliveryDate(d, 3);
order.setOrderDate(d);
order.setDeliveryDate(delivery);
order.setUser(user);
order.setItems(items);
String addOrders = orderService.addOrders(order);
System.err.println("new order add status " + addOrders + "-------------");
System.err.println(order);
// change product quantity after adding new order
for (int i = 0; i < items.size(); i++) {
Integer qSale = items.get(i).getQuantity() * (-1);
productService.rechargeProduct(items.get(i).getProduct(), qSale);
}
if (!addOrders.toLowerCase().contains("error")) {
model.setViewName("successorder");
model.addObject("order", order);
model.addObject("message", addOrders);
session.setAttribute("cart", null);
} else {
session.setAttribute("error", addOrders);
model.setViewName("redirect:/addtocartlist");
}
return model;
}
finally, here my code in dao class that save user and order.
UserDaoImpl.java
public String addUser(User user) {
String result = "";
String pass = encoder.encode(user.getPassword());
user.setPassword(pass);
try {
session().save(user);
session().flush();
result = "success";
} catch (Exception e) {
if (e.getCause().getMessage().toLowerCase().contains("duplicate"))
result = "error :user is already joined to store!";
else
result = "error :" + e.getCause().getMessage();
}
return result;
}
OrderDaoImpl.java
public String addOrders(Orders orders) {
String result = "";
try {
session().save(orders);
result = "success";
} catch (Exception e) {
if (e.getCause() != null)
if (e.getCause().getMessage().toLowerCase().contains("duplicate"))
result = "error this order already was exist";
else
result = "error " + e.getCause().getMessage();
else {
result = "error " + e.getMessage();
}
System.err.println(result);
} finally {
session().clear();
}
return result;
}
All codes are similar, but results are diffrent. when try to add new order I get this exception:
not-null property references a null or transient value:com.softup.store.entity.CartItem.order
Set both sides of relation. On every item call setOrder(). On user setOrder() also.
I'm trying to login with users from database, but I have this error. I think the problem appears in class "UserDetailsServiceImpl". What I have to do to fix this error? I will be grateful for any hint or idea...........................................................................
2018-03-16 11:13:40.389 ERROR 6520 --- [nio-8080-exec-5]
w.a.UsernamePasswordAuthenticationFilter : An internal error occurred while trying to authenticate the user.org.springframework.security.authentication.InternalAuthenticationServiceException: failed to lazily initialize a collection of role: com.continental.qtools.fingerprints.models.User.roles, could not initialize proxy - no Session
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
This is entity "User"
#Entity
#Table(name = "users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int userId;
#Column(name = "username")
#NotEmpty(message = "*Please provide your username")
private String username;
#Column(name = "password")
#Length(min = 5, message = "*Your password must have at least 5 characters")
#NotEmpty(message = "*Please provide your password")
private String password;
#Column(name = "email")
#Email(message = "*Please provide a valid Email")
#NotEmpty(message = "*Please provide an email")
private String email;
#Transient
private String passwordConfirm;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "users_roles", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "users_projects", joinColumns = #JoinColumn)
private List<Project> projects;
public User(String username, String password, String email, String passwordConfirm, Set<Role> roles,
List<Project> projects) {
super();
this.username = username;
this.password = password;
this.email = email;
this.passwordConfirm = passwordConfirm;
this.roles = roles;
this.projects = projects;
}
public User() {
// TODO Auto-generated constructor stub
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserId() {
return userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
#Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", email=" + email + ", passwordConfirm="
+ passwordConfirm + ", roles=" + roles + ", projects=" + projects + "]";
}
}
This is entity "Role"
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private int id;
#Column(name = "role")
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
UserDetailsServiceImp
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
System.out.println("User: " + user.getUsername());
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
grantedAuthorities);
}
}
Try adding a FetchType.EAGER to the roles property on the user object.
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<Role> roles;
Update: Alternative refactor with Privileges included
Authority Class instead of Role Class
#Entity
#Table(name = "authority")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Authority implements GrantedAuthority {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#ManyToMany
#JoinTable(
name = "authorities_privileges",
joinColumns = #JoinColumn(
name = "authority_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(
name = "privilege_id", referencedColumnName = "id"))
private Collection<Privilege> privileges;
public Authority() {
super();
}
public Authority(final String name) {
super();
this.name = name;
}
public Authority(String name,
Collection<Privilege> privileges) {
this.name = name;
this.privileges = privileges;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection<Privilege> getPrivileges() {
return privileges;
}
public void setPrivileges(Collection<Privilege> privileges) {
this.privileges = privileges;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj.toString().equals(this.name)) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
final Authority auth = (Authority) obj;
if (this.name != null && this.name.equals(auth.name)) {
return true;
}
return false;
}
#Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Role [name=").append(name).append("]").append("[id=").append(id).append("]");
return builder.toString();
}
#Override
#JsonIgnore
public String getAuthority() {
return name;
}
}
Privilege Class (Optional)
#Entity
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Privilege {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
private String name;
public Privilege() {
super();
}
public Privilege(final String name) {
super();
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
User Class
#Entity
#Table(name = "user_account")
public class User implements UserDetails {
#Id
#Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "username")
private String username;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#JsonIgnore
#Column(name = "password", length = 60)
private String password;
#Column(name = "enabled")
private boolean enabled;
#Column(name = "last_password_reset_date")
private Timestamp lastPasswordResetDate;
#Column(name = "is_using_2FA")
private boolean isUsing2FA;
#JsonIgnore
#Column(name = "secret", length = 60)
private String secret;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_authority",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "authority_id", referencedColumnName = "id"))
private Collection<Authority> authorities;
public User() {
this.secret = UUID.randomUUID().toString();
this.enabled = false;
}
public User(Long id,
String username, String firstName, String lastName,
String email, String password,
boolean enabled, Timestamp lastPasswordResetDate,
boolean isUsing2FA, String secret,
Collection<Authority> authorities) {
this.id = id;
this.username = username;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.enabled = enabled;
this.lastPasswordResetDate = lastPasswordResetDate;
this.isUsing2FA = isUsing2FA;
this.secret = secret;
this.authorities = authorities;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(final String username) {
this.email = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
Date date = new Date();
this.lastPasswordResetDate = new Timestamp(date.getTime());
this.password = password;
}
#Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public boolean isUsing2FA() {
return isUsing2FA;
}
public void setUsing2FA(boolean isUsing2FA) {
this.isUsing2FA = isUsing2FA;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
#Override
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Timestamp getLastPasswordResetDate() {
return lastPasswordResetDate;
}
public void setLastPasswordResetDate(Timestamp lastPasswordResetDate) {
this.lastPasswordResetDate = lastPasswordResetDate;
}
#JsonIgnore
#Override
public boolean isAccountNonExpired() {
return true;
}
#JsonIgnore
#Override
public boolean isAccountNonLocked() {
return true;
}
#JsonIgnore
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((username == null) ? 0 : username.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final User user = (User) obj;
if (!username.equals(user.username)) {
return false;
}
return true;
}
#Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("User [id=").append(id).append(", firstName=").append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", isUsing2FA=")
.append(isUsing2FA).append(", secret=").append(secret).append(", roles=").append(authorities).append("]");
return builder.toString();
}
}
UserBuilder Class
public class UserBuilder {
private Long bId;
private String bUsername;
private String bFirstName;
private String bLastName;
private String bEmail;
private String bPassword;
private boolean bEnabled;
private Timestamp bLastPasswordResetDate;
private boolean bIsUsing2FA;
private String bSecret;
private Collection<Authority> bAuthorities;
public UserBuilder() {
}
public UserBuilder(Long bId,
String bUsername, String bFirstName, String bLastName,
String bEmail, String bPassword, boolean bEnabled,
Timestamp bLastPasswordResetDate, boolean bIsUsing2FA, String bSecret,
Collection<Authority> authorities) {
this.bId = bId;
this.bUsername = bUsername;
this.bFirstName = bFirstName;
this.bLastName = bLastName;
this.bEmail = bEmail;
this.bPassword = bPassword;
this.bEnabled = bEnabled;
this.bLastPasswordResetDate = bLastPasswordResetDate;
this.bIsUsing2FA = bIsUsing2FA;
this.bSecret = bSecret;
this.bAuthorities = bAuthorities;
}
public UserBuilder(User user) {
this.bId = user.getId();
this.bUsername = user.getUsername();
this.bFirstName = user.getFirstName();
this.bLastName = user.getLastName();
this.bEmail = user.getEmail();
this.bPassword = user.getPassword();
this.bEnabled = user.isEnabled();
this.bLastPasswordResetDate = user.getLastPasswordResetDate();
this.bIsUsing2FA = user.isUsing2FA();
this.bSecret = user.getSecret();
}
public User createUser() {
return new User(bId,
bUsername,
bFirstName,
bLastName,
bEmail,
bPassword,
bEnabled,
bLastPasswordResetDate,
bIsUsing2FA,
bSecret,
bAuthorities
);
}
public UserBuilder bId(Long bId) {
this.bId = bId;
return this;
}
public UserBuilder bUsername(String bUsername) {
this.bUsername = bUsername;
return this;
}
public UserBuilder bFirstName(String bFirstName) {
this.bFirstName = bFirstName;
return this;
}
public UserBuilder bLastName(String bLastName) {
this.bLastName = bLastName;
return this;
}
public UserBuilder bEmail(String bEmail) {
this.bEmail = bEmail;
return this;
}
public UserBuilder bPassword(String bPassword) {
Date date = new Date();
this.bLastPasswordResetDate = new Timestamp(date.getTime());
this.bPassword = bPassword;
return this;
}
public UserBuilder bEnabled(boolean bEnabled) {
this.bEnabled = bEnabled;
return this;
}
public UserBuilder bLastPasswordResetDate(Timestamp bLastPasswordResetDate) {
this.bLastPasswordResetDate = bLastPasswordResetDate;
return this;
}
public UserBuilder bIsUsing2FA(boolean bIsUsing2FA) {
this.bIsUsing2FA = bIsUsing2FA;
return this;
}
public UserBuilder bSecret(String bSecret) {
this.bSecret = bSecret;
return this;
}
public UserBuilder bAuthorities(Collection<Authority> bAuthorities) {
this.bAuthorities = bAuthorities;
return this;
}
}
CustomUserDetailsService Class
#Service("userDetailsService")
#Transactional
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#SuppressWarnings("unchecked")
#Override
public UserDetails loadUserByUsername(final String identity) throws UsernameNotFoundException {
try {
final User user = Optional.ofNullable(userRepository.findByEmail(identity)).orElseGet(() -> userRepository.findByUsername(identity));
if (user == null) {
throw new UsernameNotFoundException("No user found with username: " + identity);
}
//Collection<Authority> authorities = getAuthorities((Collection<Authority>) user.getAuthorities());
Collection<Authority> authorities = getAuthorities((Collection<Authority>) user.getAuthorities());
return new UserBuilder(user).bAuthorities(authorities).createUser();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
private final Collection<Authority> getAuthorities(final Collection<Authority> authorityList) {
return getGrantedAuthorities(getAuthorityList(authorityList));
}
private final List<String> getAuthorityList(final Collection<Authority> authorityList) {
final List<String> authorities = new ArrayList<String>();
for (final Authority authority : authorityList) {
authorities.add(authority.getName());
if (authority.getPrivileges() == null || authority.getPrivileges().isEmpty()) continue;
// Add all Privileges as Authorities
for (final Privilege item : authority.getPrivileges()) {
authorities.add(item.getName());
}
}
return authorities;
}
private final Collection<Authority> getGrantedAuthorities(final List<String> authorityList) {
final List<Authority> grantedAuthorities = new ArrayList<Authority>();
for (final String authority : authorityList) {
grantedAuthorities.add(new Authority(authority));
}
return grantedAuthorities;
}
}
Repos
public interface PrivilegeRepository extends JpaRepository<Privilege, Long> {
Privilege findByName(String name);
#Override
void delete(Privilege privilege);
}
public interface RoleRepository extends JpaRepository<Authority, Long> {
Authority findByName(String name);
#Override
void delete(Authority role);
}
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
User findByUsername(String username);
#Override
void delete(User user);
}
SetupDataLoader Class (Optional)
#Component
public class SetupDataLoader implements ApplicationListener<ContextRefreshedEvent> {
private boolean alreadySetup = false;
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
#Autowired
private PrivilegeRepository privilegeRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
BeerRepository beerRepository;
#Override
#Transactional
public void onApplicationEvent(final ContextRefreshedEvent event) {
if (alreadySetup) {
return;
}
// == create initial privileges
final Privilege userReadPrivilege = createPrivilegeIfNotFound("USER_READ_PRIVILEGE");
final Privilege userWritePrivilege = createPrivilegeIfNotFound("USER_WRITE_PRIVILEGE");
final Privilege beerReadPrivilege = createPrivilegeIfNotFound("BEER_READ_PRIVILEGE");
final Privilege beerWritePrivilege = createPrivilegeIfNotFound("BEER_WRITE_PRIVILEGE");
final Privilege passwordPrivilege = createPrivilegeIfNotFound("CHANGE_PASSWORD_PRIVILEGE");
// == create initial roles
final List<Privilege> adminPrivileges = new ArrayList<Privilege>(Arrays.asList(beerReadPrivilege, beerWritePrivilege, userReadPrivilege, userWritePrivilege, passwordPrivilege));
final List<Privilege> userPrivileges = new ArrayList<Privilege>(Arrays.asList(beerReadPrivilege, beerWritePrivilege));
final Authority adminAuthority = createRoleIfNotFound("ROLE_ADMIN", adminPrivileges);
createRoleIfNotFound("ROLE_USER", userPrivileges);
// == create initial user
createUserIfNotFound("rdurden",
"rdurden#example.com",
"Rupert",
"Durden",
"ILikeBeer2!",
new ArrayList<Authority>(Arrays.asList(adminAuthority)));
alreadySetup = true;
}
#Transactional
Privilege createPrivilegeIfNotFound(final String name) {
Privilege privilege = privilegeRepository.findByName(name);
if (privilege == null) {
privilege = new Privilege(name);
privilege = privilegeRepository.save(privilege);
}
return privilege;
}
#Transactional
Authority createRoleIfNotFound(final String name, final Collection<Privilege> privileges) {
Authority authority = roleRepository.findByName(name);
if (authority == null) {
authority = new Authority(name);
}
authority.setPrivileges(privileges);
authority = roleRepository.save(authority);
return authority;
}
#Transactional
User createUserIfNotFound(final String username, final String email, final String firstName, final String lastName, final String password, final Collection<Authority> authorities) {
User user = Optional.ofNullable(userRepository.findByEmail(email)).orElseGet(() -> userRepository.findByUsername(username));
if (user != null) return user;
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -1);
Date lastMonthDate = cal.getTime();
Timestamp lastMonthTimestamp = new Timestamp(lastMonthDate.getTime());
user = new UserBuilder()
.bAuthorities(authorities)
.bUsername(username)
.bFirstName(firstName)
.bLastName(lastName)
.bEmail(email)
.bPassword(passwordEncoder.encode(password))
.bIsUsing2FA(false)
.bEnabled(true)
.bLastPasswordResetDate(lastMonthTimestamp)
.createUser();
user = userRepository.save(user);
return user;
}
}
Try adding #Transactional to method loadUserByUsername.
I am working on a web application using:
Spring Boot
PostgreSQL
JPA and Hibernate.
I have a table called role and another page. Among them there is a many-to-many table with ID's. What I'm trying to get is the list of pages that correspond to a role, so I'm trying to retrieve the list of pages from the id of the role and executing a query to bring the list. The problem is that I have an error in the ResultSet because it tells me that it does not find a column with the name page_id.
Example:
I have executed the query separately and this brings me results correctly.
select p.url from role_page rp, page p where rp.role_id = 6 and rp.page_id = p.page_id;
Output:
Output of the query
Then I made a call to the function to get the list and check it to make sure I get results.
public void rolesAndPages(){
List<Page> pages = pageRepository.findPagePerRole(6);
for (Page page: pages
) {
System.out.println(page.getUrl());
}
}
And throws the error described above:
org.postgresql.util.PSQLException: The column name page_id was not found in this ResultSet.
My Repository:
#Repository("pageRepository")
public interface PageRepository extends JpaRepository<Page, Long> {
#Query(value = "select p.url from role_page rp, page p where rp.role_id = ?1 and rp.page_id = p.page_id", nativeQuery = true)
List<Page> findPagePerRole(Integer id);
}
Role.java
#Entity
#Table(name = "app_role")
public class Role {
#Id
#SequenceGenerator(name="pk_sequence",sequenceName="messagesounds_id_seq", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence")
#Column(name="role_id")
private int id;
#Column(name="authority")
#NotEmpty(message = "*Please provide a name")
private String authority;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "role_page", joinColumns = #JoinColumn(name = "role_id"), inverseJoinColumns = #JoinColumn(name = "page_id"))
private Set<Page> pages;
public void setPages(Set<Page> pages) {
this.pages = pages;
}
public Set<Page> getPages() {
return pages;
}
public Role() {}
public Role(String authority) {
this.authority = authority;
}
public Role(String authority, Set<Page> pages){
this.authority = authority;
this.pages = pages;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
}
Page.java
#Entity
#Table(name = "page")
public class Page {
#Id
#SequenceGenerator(name = "pk_sequence", sequenceName = "messagesounds_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk_sequence")
#Column(name = "page_id")
private int id;
#Column(name = "name_page")
#NotEmpty(message = "*Please provide a name")
private String name;
#Column(name = "url")
#NotEmpty(message = "*Please provide an url")
private String url;
#Column(name = "description")
#NotEmpty(message = "*Please provide a description")
private String description;
#ManyToMany(mappedBy = "pages")
private Set<Role> roles;
public Page() {
}
public Page(String name_page) {
this.name = name_page;
}
public Page(String name_page, Set<Role> roles) {
this.name = name_page;
this.roles = roles;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
The error is quite explicite, you need to select page_id column to make it work, not only p.url.
Try this to retrieve every column of Page :
#Query(value = "select p.* from role_page rp, page p where rp.role_id = ?1 and rp.page_id = p.page_id", nativeQuery = true)
Or, this to retrieve every columns of tables Page and Role_Page :
#Query(value = "from role_page rp, page p where rp.role_id = ?1 and rp.page_id = p.page_id", nativeQuery = true)
The both queries should work.
Did you tried :
#Query(value = "select p.url from role_page rp, page p where rp.id = ?1 and rp.id = p.id")
I am using Hibernate with Spring in my project, I want to write a HQL query to get and update the role of user. How can I do that
This is my ERD:
this is my java classes:
User
#Entity
#Table(name = "users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId")
private int userId;
#Column(name = "userIdCardNo")
private String useridcardno;
#Column(name = "userFname")
private String fname;
#Column(name = "userMname")
private String mname;
#Column(name = "userLname")
private String lname;
#Column(name = "userPhone")
private int phone;
#Column(name = "userPhone2")
private String phone2;
#Column(name = "userAddress")
private String address;
#Column(name = "userAddress2")
private String address2;
#Column(name = "userName")
private String username;
#Column(name = "userPass")
private String password;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "users_roles", joinColumns = #JoinColumn(name = "userId", nullable = false) , inverseJoinColumns = #JoinColumn(name = "roleId", nullable = false) )
private List<Role> roles;
#Enumerated(EnumType.STRING)
#Column(name = "userStatus")
private UserStatus status;
//CREATE MD5 from String
public static String md5(String input) {
String md5 = null;
if (null == input)
return null;
try {
// Create MessageDigest object for MD5
MessageDigest digest = MessageDigest.getInstance("MD5");
// Update input string in message digest
digest.update(input.getBytes(), 0, input.length());
// Converts message digest value in base 16 (hex)
md5 = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
//CONTRUSCTORS
public User() {
}
public User(int userId, String useridcardno, String fname, String mname, String lname, int phone, String phone2,
String address, String address2, String username, String password, List<Role> roles, UserStatus status) {
super();
this.userId = userId;
this.useridcardno = useridcardno;
this.fname = fname;
this.mname = mname;
this.lname = lname;
this.phone = phone;
this.phone2 = phone2;
this.address = address;
this.address2 = address2;
this.username = username;
this.password = BCrypt.hashpw(password, BCrypt.gensalt());
this.roles = roles;
this.status = status;
}
//GETTERS and SETTERS
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUseridcardno() {
return useridcardno;
}
public void setUseridcardno(String useridcardno) {
this.useridcardno = useridcardno;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getMname() {
return mname;
}
public void setMname(String mname) {
this.mname = mname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
public String getPhone2() {
return phone2;
}
public void setPhone2(String phone2) {
this.phone2 = phone2;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public UserStatus getStatus() {
return status;
}
public void setStatus(UserStatus status) {
this.status = status;
}
}
Role
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "roleId")
private int id;
#Column(name = "roleName")
private String roleName;
#ManyToMany(fetch = FetchType.EAGER, mappedBy = "roles")
private List<User> users;
public Role() {
}
public Role(int id, String roleName, List<User> users) {
super();
this.id = id;
this.roleName = roleName;
this.users = users;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
And UsersRoles
#Entity
#Table(name="users_roles")
public class UsersRoles {
#Id
#Column(name="userId")
private int userId;
#Id
#Column(name="roleId")
private int roleId;
public UsersRoles() {
}
public UsersRoles(int userId, int roleId) {
super();
this.userId = userId;
this.roleId = roleId;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
}
I'm quite new to database queries since I have tried with for only a few times. I can get the data in one table, but for joining tables like this, I really need a hint.
Just load the user and modifiy the items of the role list. Then commit the transaction. - That's all.
EntityManager em ...
...
<begin Transaction>
...
User user = em.find(User.class, 1); //load by id 1 - just for example
User role1 = em.find(Role.class, 1); //load by id 1 - just for example
user.getRoles().add(role1);
...
<commit Transaction>
It is so simple because you use an ORM (Object Relational Mapper)(Hibernate). I almost all cases there is no need to write queries for updates, instead the state of the objects gets persisted.
I have a problem. Here my entities user and userRole
User
package com.springapp.model;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
#Entity
#Table(name = "users", catalog = "users")
public class User {
private String username;
private String password;
private boolean enabled;
private String email;
private String token;
private Set<UserRole> userRole = new HashSet<UserRole>(0);
public User() {
this.enabled=false;
}
#Column(name = "token",
nullable = false, length = 80)
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
public String getEmail() {
return this.email;
}
#Column(name = "email",
nullable = false, length = 80)
public void setEmail(String email) {
this.email = email;
}
#Id
#Column(name = "username", unique = true,
nullable = false, length = 45)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password",
nullable = false, length = 60)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "enabled", nullable = false)
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
public Set<UserRole> getUserRole() {
return this.userRole;
}
public void setUserRole(Set<UserRole> userRole) {
this.userRole = userRole;
}
}
UserRole
package com.springapp.model;
import javax.persistence.*;
import static javax.persistence.GenerationType.IDENTITY;
#Entity
#Table(name = "user_roles", uniqueConstraints = #UniqueConstraint(
columnNames = { "role", "username" }))
public class UserRole{
private Integer userRoleId;
private User user;
private String role;
public UserRole() {
}
public UserRole(User user, String role) {
this.user = user;
this.role = role;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_role_id",
unique = true, nullable = false)
public Integer getUserRoleId() {
return this.userRoleId;
}
public void setUserRoleId(Integer userRoleId) {
this.userRoleId = userRoleId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "username", nullable = false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "role", nullable = false, length = 45)
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
}
Now I want to get list of users with lists of their roles to json using gson lib
List<User> users = userService.showAllUsers();
Gson gson = new Gson();
return gson.toJson(users);
But it fails with stackoverflow error. I think it's because every user refers to roles and roles refers to users (because we have User user in Userroles and Set of roles in users). And it turns "recursion". How can I avoid this error?
That happens when you bidirectional associations and JSon doesn't ignore one side.
You need to mark the many-to-one side with #JsonIgnore:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "username", nullable = false)
#JsonIgnore
public User getUser() {
return this.user;
}