Reputation: 91
I have a UserEntity and a RoleEntity. The UserEntity contains a field "roles" which is of type HashSet and annotated with the @ManyToMany annotation. When calling my custom query "findByEmail" it successfully fetches the UserEntity, but the roles set keeps empty.
Here some parts of the code:
package xyz.michaeltprojects.collchecklist.security.persistence;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Entity
@Table(name = "users")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class UserEntity {
@Id
@GeneratedValue
private UUID id;
@NotBlank
@Size(min = 3, max = 30)
private String username;
@NotBlank
@Size(min = 6, max = 50)
@Email
private String email;
@NotBlank
@Size(max = 120)
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<RoleEntity> roles = new HashSet<>();
}
package xyz.michaeltprojects.collchecklist.security.persistence;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "roles")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class RoleEntity {
@Id
@GeneratedValue
private UUID id;
@Enumerated(EnumType.STRING)
@Column(length = 20)
private ERole name;
}
package xyz.michaeltprojects.collchecklist.security.persistence;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import java.util.UUID;
@Repository
public interface UserRepository extends JpaRepository<UserEntity, UUID> {
Optional<UserEntity> findByEmail(String email);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
Upvotes: 3
Views: 5041
Reputation: 11
I had same issue and I could not get any values. When I used List
instead of Set
everything is fine.
I found out that there is a problem with hashcode
and equals
generated by Lombok. When I generated them manually everything works.
https://jpa-buddy.com/blog/lombok-and-jpa-what-may-go-wrong/
Upvotes: 1
Reputation: 4032
I had the same issue. In my case, I was using hibernate and liquibase to update the schema. After updating the schema with liquibase and inserting some data using liquibase, I could not get any associated value with manytomany relationship.
After changing Set to List. I was able to get values Like this
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
@OrderBy(value = "createdOn")
private Set<UserAppServices> userAppServices;
To
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
@OrderBy(value = "createdOn")
private List<UserAppServices> userAppServices;
Upvotes: 2
Reputation: 39
Try to use List roles = new ArrayList<>()
In my code, I have used Set with ManyToMany relationship and I didn't get any associated vale after I changed the Set to List. I didn't understand Why the Set with hashSet didn't work.
Upvotes: 3
Reputation: 91
I've somehow solved the issue... It seems that populating the relationships didn't work with UUIDs as identifiers. When I replaced them with longs it worked perfectly. Seems weird but it is like it is
Upvotes: 1
Reputation: 3
Can you try this? by adding an override function setRoles(..) below the UserEntity calss
package xyz.michaeltprojects.collchecklist.security.persistence;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Entity
@Table(name = "users")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class UserEntity {
@Id
@GeneratedValue
private UUID id;
@NotBlank
@Size(min = 3, max = 30)
private String username;
@NotBlank
@Size(min = 6, max = 50)
@Email
private String email;
@NotBlank
@Size(max = 120)
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<RoleEntity> roles = new HashSet<>();
public UserEntity setRoles(final Set<RoleEntity> roles) {
this.roles.clear();
if (roles != null) {
this.roles.addAll(roles);
}
return this;
}
}
Upvotes: 0
Reputation: 1667
You ManyToMany
is not correct, you need to reference the id of each table by using referencedColumnName
Take a look at this one:
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<RoleEntity> roles;
Upvotes: 0