简体   繁体   中英

How can I implement a JPQL query retrieving all the user having a specific type (implemented using a MANY TO MANY relation)?

I am working on a Spring Boot project and I am not so into Hibernate/JPA and I have the following doubt about how can I use it to perform the following query.

I have these 2 entity classes:

User : it contains records representing user on my portal:

@Entity
@Table(name = "portal_user")
@Getter
@Setter
public class User implements Serializable {
     
    private static final long serialVersionUID = 5062673109048808267L;
    
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "first_name")
    @NotNull(message = "{NotNull.User.firstName.Validation}")
    private String firstName;
    
    @Column(name = "middle_name")
    private String middleName;
    
    @Column(name = "surname")
    @NotNull(message = "{NotNull.User.surname.Validation}")
    private String surname;
    
    @Column(name = "sex")
    @NotNull(message = "{NotNull.User.sex.Validation}")
    private char sex;
    
    @Column(name = "birthdate")
    @NotNull(message = "{NotNull.User.birthdate.Validation}")
    private Date birthdate;
    
    @Column(name = "tax_code")
    @NotNull(message = "{NotNull.User.taxCode.Validation}")
    private String taxCode;
    
    @Column(name = "e_mail")
    @NotNull(message = "{NotNull.User.email.Validation}")
    private String email;
    
    //private String test;
    
    @Column(name = "pswd")
    @NotNull(message = "{NotNull.User.pswd.Validation}")
    private String pswd;
    
    @Column(name = "contact_number")
    @NotNull(message = "{NotNull.User.contactNumber.Validation}")
    private String contactNumber;
    
    @Temporal(TemporalType.DATE)
    @Column(name = "created_at")
    private Date createdAt;
    
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
    @JsonManagedReference
    private Set<Address> addressesList = new HashSet<>();
    
    @ManyToMany(cascade = { CascadeType.MERGE })
    @JoinTable(
        name = "portal_user_user_type", 
        joinColumns = { @JoinColumn(name = "portal_user_id_fk") }, 
        inverseJoinColumns = { @JoinColumn(name = "user_type_id_fk") }
    )
    Set<UserType> userTypes;
    

    public User() {
        super();
        // TODO Auto-generated constructor stub
    }


    public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
            String email, String pswd, String contactNumber, Date createdAt) {
        super();
        this.firstName = firstName;
        this.middleName = middleName;
        this.surname = surname;
        this.sex = sex;
        this.birthdate = birthdate;
        this.taxCode = taxCode;
        this.email = email;
        this.pswd = pswd;
        this.contactNumber = contactNumber;
        this.createdAt = createdAt;
    }

}

Each user can be associated with one or more roles reppresented by this MANY TO MANY relationship:

@ManyToMany(cascade = { CascadeType.MERGE })
@JoinTable(
    name = "portal_user_user_type", 
    joinColumns = { @JoinColumn(name = "portal_user_id_fk") }, 
    inverseJoinColumns = { @JoinColumn(name = "user_type_id_fk") }
)
Set<UserType> userTypes;

As you can see this field is associated to a DB table named portal_user_user_type that simply contains the PK of the user table and the PK of the user_type table represented by the following entity class:

@Entity
@Table(name = "user_type")
@Getter
@Setter
public class UserType implements Serializable {
    
    private static final long serialVersionUID = 6904959949570501298L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "type_name")
    private String typeName;
    
    @Column(name = "description")
    private String description;
    
    //@OneToMany(mappedBy = "userType")
    //@JsonManagedReference
    //private Set<User_UserType> userToUserTypeAssociation = new HashSet<>();
    
    @ManyToMany(cascade = { CascadeType.MERGE })
    @JoinTable(
        name = "user_type_operation", 
        joinColumns = { @JoinColumn(name = "fk_user_type_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "fk_operation_id") }
    )
    Set<Operation> operations;
    

    public UserType() {
        super();
        // TODO Auto-generated constructor stub
    }
    
    public UserType(String typeName, String description) {
        super();
        this.typeName = typeName;
        this.description = description;
    }

}

Now the previous class is mapping the user_type database typological table that can contains only a specific set of values. For example having typeName like ADMIN or AGENT or CLIENT .

Into my Spring Boot project I have this repository interface implementing JpaRepository interface:

public interface UsersRepository extends JpaRepository<User, Integer> {
    
    User findByemail(String email);

}

At the moment it contains onlya query implemented using the "query by method name" tecnique.

Now I have to implement another more complex query based on the previous entity classes:

I have to retrieve all the User instance having a specific UserType.typeName value.

For example: retrieve all the User record having UserType.typeName equals to ADMIN .

Is it possible implement it using the query by method name style or is it better to use JPQL. In case how can I create a query like this? (also in JPQL is ok)

you can use @Query annotation in order to write your query or you can use findByUserTypes_TypeNameIn(List typeNameList) for a list of user type names or findByUserTypes_TypeName(String typeName) for a specific type name.

Hope it helps.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM